mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-11 11:29:42 +02:00
#1295 Drawing edges between nodes
This commit is contained in:
@@ -36,10 +36,16 @@
|
|||||||
<div class="mermaid" style="width: 100%; height: 100%">
|
<div class="mermaid" style="width: 100%; height: 100%">
|
||||||
graph TB
|
graph TB
|
||||||
A[apan klättrar]-- i träd -->B
|
A[apan klättrar]-- i träd -->B
|
||||||
|
subgraph Test
|
||||||
|
B
|
||||||
|
end
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid" style="width: 100%; height: 100%">
|
<div class="mermaid" style="width: 100%; height: 100%">
|
||||||
flowchart TB
|
flowchart TB
|
||||||
A[apan klättrar]-- i träd -->B
|
A[apan klättrar]-- i träd -->B
|
||||||
|
subgraph Test
|
||||||
|
B
|
||||||
|
end
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="./mermaid.js"></script>
|
<script src="./mermaid.js"></script>
|
||||||
|
@@ -34,18 +34,18 @@ export const positionEdgeLabel = edge => {
|
|||||||
el.attr('transform', 'translate(' + edge.x + ', ' + edge.y + ')');
|
el.attr('transform', 'translate(' + edge.x + ', ' + edge.y + ')');
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRelationType = function(type) {
|
// const getRelationType = function(type) {
|
||||||
switch (type) {
|
// switch (type) {
|
||||||
case stateDb.relationType.AGGREGATION:
|
// case stateDb.relationType.AGGREGATION:
|
||||||
return 'aggregation';
|
// return 'aggregation';
|
||||||
case stateDb.relationType.EXTENSION:
|
// case stateDb.relationType.EXTENSION:
|
||||||
return 'extension';
|
// return 'extension';
|
||||||
case stateDb.relationType.COMPOSITION:
|
// case stateDb.relationType.COMPOSITION:
|
||||||
return 'composition';
|
// return 'composition';
|
||||||
case stateDb.relationType.DEPENDENCY:
|
// case stateDb.relationType.DEPENDENCY:
|
||||||
return 'dependency';
|
// return 'dependency';
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const insertEdge = function(elem, edge) {
|
export const insertEdge = function(elem, edge) {
|
||||||
// The data for our line
|
// The data for our line
|
||||||
|
@@ -7,7 +7,7 @@ import { logger } from '../logger';
|
|||||||
export const render = (elem, graph) => {
|
export const render = (elem, graph) => {
|
||||||
insertMarkers(elem);
|
insertMarkers(elem);
|
||||||
|
|
||||||
const clusters = elem.insert('g').attr('class', 'clusters');
|
const clusters = elem.insert('g').attr('class', 'clusters'); // eslint-disable-line
|
||||||
const edgePaths = elem.insert('g').attr('class', 'edgePaths');
|
const edgePaths = elem.insert('g').attr('class', 'edgePaths');
|
||||||
const edgeLabels = elem.insert('g').attr('class', 'edgeLabels');
|
const edgeLabels = elem.insert('g').attr('class', 'edgeLabels');
|
||||||
const nodes = elem.insert('g').attr('class', 'nodes');
|
const nodes = elem.insert('g').attr('class', 'nodes');
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
var intersectEllipse = require("./intersect-ellipse");
|
import intersectEllipse from './intersect-ellipse';
|
||||||
|
|
||||||
module.exports = intersectCircle;
|
|
||||||
|
|
||||||
function intersectCircle(node, rx, point) {
|
function intersectCircle(node, rx, point) {
|
||||||
return intersectEllipse(node, rx, rx, point);
|
return intersectEllipse(node, rx, rx, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default intersectCircle;
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
module.exports = intersectEllipse;
|
|
||||||
|
|
||||||
function intersectEllipse(node, rx, ry, point) {
|
function intersectEllipse(node, rx, ry, point) {
|
||||||
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
||||||
|
|
||||||
@@ -11,11 +9,11 @@ function intersectEllipse(node, rx, ry, point) {
|
|||||||
|
|
||||||
var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px);
|
var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px);
|
||||||
|
|
||||||
var dx = Math.abs(rx * ry * px / det);
|
var dx = Math.abs((rx * ry * px) / det);
|
||||||
if (point.x < cx) {
|
if (point.x < cx) {
|
||||||
dx = -dx;
|
dx = -dx;
|
||||||
}
|
}
|
||||||
var dy = Math.abs(rx * ry * py / det);
|
var dy = Math.abs((rx * ry * py) / det);
|
||||||
if (point.y < cy) {
|
if (point.y < cy) {
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
}
|
}
|
||||||
@@ -23,3 +21,4 @@ function intersectEllipse(node, rx, ry, point) {
|
|||||||
return { x: cx + dx, y: cy + dy };
|
return { x: cx + dx, y: cy + dy };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default intersectEllipse;
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
module.exports = intersectLine;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the point at which two lines, p and q, intersect or returns
|
* Returns the point at which two lines, p and q, intersect or returns
|
||||||
* undefined if they do not intersect.
|
* undefined if they do not intersect.
|
||||||
@@ -17,36 +15,36 @@ function intersectLine(p1, p2, q1, q2) {
|
|||||||
// b1 y + c1 = 0.
|
// b1 y + c1 = 0.
|
||||||
a1 = p2.y - p1.y;
|
a1 = p2.y - p1.y;
|
||||||
b1 = p1.x - p2.x;
|
b1 = p1.x - p2.x;
|
||||||
c1 = (p2.x * p1.y) - (p1.x * p2.y);
|
c1 = p2.x * p1.y - p1.x * p2.y;
|
||||||
|
|
||||||
// Compute r3 and r4.
|
// Compute r3 and r4.
|
||||||
r3 = ((a1 * q1.x) + (b1 * q1.y) + c1);
|
r3 = a1 * q1.x + b1 * q1.y + c1;
|
||||||
r4 = ((a1 * q2.x) + (b1 * q2.y) + c1);
|
r4 = a1 * q2.x + b1 * q2.y + c1;
|
||||||
|
|
||||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
||||||
// same side of line 1, the line segments do not intersect.
|
// same side of line 1, the line segments do not intersect.
|
||||||
if ((r3 !== 0) && (r4 !== 0) && sameSign(r3, r4)) {
|
if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
|
||||||
return /*DONT_INTERSECT*/;
|
return /*DONT_INTERSECT*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
||||||
a2 = q2.y - q1.y;
|
a2 = q2.y - q1.y;
|
||||||
b2 = q1.x - q2.x;
|
b2 = q1.x - q2.x;
|
||||||
c2 = (q2.x * q1.y) - (q1.x * q2.y);
|
c2 = q2.x * q1.y - q1.x * q2.y;
|
||||||
|
|
||||||
// Compute r1 and r2
|
// Compute r1 and r2
|
||||||
r1 = (a2 * p1.x) + (b2 * p1.y) + c2;
|
r1 = a2 * p1.x + b2 * p1.y + c2;
|
||||||
r2 = (a2 * p2.x) + (b2 * p2.y) + c2;
|
r2 = a2 * p2.x + b2 * p2.y + c2;
|
||||||
|
|
||||||
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
||||||
// on same side of second line segment, the line segments do
|
// on same side of second line segment, the line segments do
|
||||||
// not intersect.
|
// not intersect.
|
||||||
if ((r1 !== 0) && (r2 !== 0) && (sameSign(r1, r2))) {
|
if (r1 !== 0 && r2 !== 0 && sameSign(r1, r2)) {
|
||||||
return /*DONT_INTERSECT*/;
|
return /*DONT_INTERSECT*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Line segments intersect: compute intersection point.
|
// Line segments intersect: compute intersection point.
|
||||||
denom = (a1 * b2) - (a2 * b1);
|
denom = a1 * b2 - a2 * b1;
|
||||||
if (denom === 0) {
|
if (denom === 0) {
|
||||||
return /*COLLINEAR*/;
|
return /*COLLINEAR*/;
|
||||||
}
|
}
|
||||||
@@ -56,11 +54,11 @@ function intersectLine(p1, p2, q1, q2) {
|
|||||||
// The denom/2 is to get rounding instead of truncating. It
|
// The denom/2 is to get rounding instead of truncating. It
|
||||||
// is added or subtracted to the numerator, depending upon the
|
// is added or subtracted to the numerator, depending upon the
|
||||||
// sign of the numerator.
|
// sign of the numerator.
|
||||||
num = (b1 * c2) - (b2 * c1);
|
num = b1 * c2 - b2 * c1;
|
||||||
x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
|
x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||||
|
|
||||||
num = (a2 * c1) - (a1 * c2);
|
num = a2 * c1 - a1 * c2;
|
||||||
y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
|
y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||||
|
|
||||||
return { x: x, y: y };
|
return { x: x, y: y };
|
||||||
}
|
}
|
||||||
@@ -68,3 +66,5 @@ function intersectLine(p1, p2, q1, q2) {
|
|||||||
function sameSign(r1, r2) {
|
function sameSign(r1, r2) {
|
||||||
return r1 * r2 > 0;
|
return r1 * r2 > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default intersectLine;
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
/* eslint "no-console": off */
|
/* eslint "no-console": off */
|
||||||
|
|
||||||
var intersectLine = require("./intersect-line");
|
import intersectLine from './intersect-line';
|
||||||
|
|
||||||
module.exports = intersectPolygon;
|
export default intersectPolygon;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the point ({x, y}) at which the point argument intersects with the
|
* Returns the point ({x, y}) at which the point argument intersects with the
|
||||||
@@ -27,15 +27,19 @@ function intersectPolygon(node, polyPoints, point) {
|
|||||||
for (var i = 0; i < polyPoints.length; i++) {
|
for (var i = 0; i < polyPoints.length; i++) {
|
||||||
var p1 = polyPoints[i];
|
var p1 = polyPoints[i];
|
||||||
var p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
var p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||||
var intersect = intersectLine(node, point,
|
var intersect = intersectLine(
|
||||||
{x: left + p1.x, y: top + p1.y}, {x: left + p2.x, y: top + p2.y});
|
node,
|
||||||
|
point,
|
||||||
|
{ x: left + p1.x, y: top + p1.y },
|
||||||
|
{ x: left + p2.x, y: top + p2.y }
|
||||||
|
);
|
||||||
if (intersect) {
|
if (intersect) {
|
||||||
intersections.push(intersect);
|
intersections.push(intersect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!intersections.length) {
|
if (!intersections.length) {
|
||||||
console.log("NO INTERSECTION FOUND, RETURN NODE CENTER", node);
|
console.log('NO INTERSECTION FOUND, RETURN NODE CENTER', node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +54,7 @@ function intersectPolygon(node, polyPoints, point) {
|
|||||||
var qdy = q.y - point.y;
|
var qdy = q.y - point.y;
|
||||||
var distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
var distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||||
|
|
||||||
return (distp < distq) ? -1 : (distp === distq ? 0 : 1);
|
return distp < distq ? -1 : distp === distq ? 0 : 1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return intersections[0];
|
return intersections[0];
|
||||||
|
@@ -6,11 +6,10 @@ import flowDb from './flowDb';
|
|||||||
import flow from './parser/flow';
|
import flow from './parser/flow';
|
||||||
import { getConfig } from '../../config';
|
import { getConfig } from '../../config';
|
||||||
|
|
||||||
import { render, addShape } from '../../dagre-wrapper/index.js';
|
import { render } from '../../dagre-wrapper/index.js';
|
||||||
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||||
import { logger } from '../../logger';
|
import { logger } from '../../logger';
|
||||||
import { interpolateToCurve, getStylesFromArray } from '../../utils';
|
import { interpolateToCurve, getStylesFromArray } from '../../utils';
|
||||||
import flowChartShapes from './flowChartShapes';
|
|
||||||
|
|
||||||
const conf = {};
|
const conf = {};
|
||||||
export const setConf = function(cnf) {
|
export const setConf = function(cnf) {
|
||||||
|
@@ -1,42 +0,0 @@
|
|||||||
import dagre from 'dagre';
|
|
||||||
import graphlib from 'graphlib';
|
|
||||||
|
|
||||||
// Create a new directed graph
|
|
||||||
var g = new dagre.graphlib.Graph({ compound: true });
|
|
||||||
|
|
||||||
// Set an object for the graph label
|
|
||||||
g.setGraph({});
|
|
||||||
|
|
||||||
// Default to assigning a new object as a label for each new edge.
|
|
||||||
g.setDefaultEdgeLabel(function() {
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add nodes to the graph. The first argument is the node id. The second is
|
|
||||||
// metadata about the node. In this case we're going to add labels to each of
|
|
||||||
// our nodes.
|
|
||||||
g.setNode('root', { label: 'Cluster' });
|
|
||||||
g.setNode('kspacey', { label: 'Kevin Spacey', width: 144, height: 100, x: 200 });
|
|
||||||
// g.setParent('kspacey', 'root');
|
|
||||||
g.setNode('swilliams', { label: 'Saul Williams', width: 160, height: 100 });
|
|
||||||
// g.setNode('bpitt', { label: 'Brad Pitt', width: 108, height: 100 });
|
|
||||||
// g.setNode('hford', { label: 'Harrison Ford', width: 168, height: 100 });
|
|
||||||
// g.setNode('lwilson', { label: 'Luke Wilson', width: 144, height: 100 });
|
|
||||||
// g.setNode('kbacon', { label: 'Kevin Bacon', width: 121, height: 100 });
|
|
||||||
|
|
||||||
// Add edges to the graph.
|
|
||||||
g.setEdge('kspacey', 'swilliams');
|
|
||||||
g.setEdge('swilliams');
|
|
||||||
// g.setEdge('swilliams', 'kbacon');
|
|
||||||
// g.setEdge('bpitt', 'kbacon');
|
|
||||||
// g.setEdge('hford', 'lwilson');
|
|
||||||
// g.setEdge('lwilson', 'kbacon');
|
|
||||||
|
|
||||||
dagre.layout(g);
|
|
||||||
|
|
||||||
g.nodes().forEach(function(v) {
|
|
||||||
console.log('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
|
||||||
});
|
|
||||||
g.edges().forEach(function(e) {
|
|
||||||
console.log('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
|
|
||||||
});
|
|
Reference in New Issue
Block a user