Merge pull request #2257 from mermaid-js/2256_class_switch_to_ng_renderer

Switch default renderer for class diagrams to the next generation renderer
This commit is contained in:
Ashish Jain 2021-08-26 18:08:48 +02:00 committed by GitHub
commit bae74bcc95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 443 additions and 421 deletions

View File

@ -1,406 +1,411 @@
/* eslint-env jest */ /* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util'; import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Class diagram', () => { describe('Class diagram', () => {
it('1: should render a simple class diagram', () => { it('1: should render a simple class diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01 <|-- AveryLongClass : Cool Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01 &lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04 Class03 *-- Class04
Class05 o-- Class06 Class05 o-- Class06
Class07 .. Class08 Class07 .. Class08
Class09 --> C2 : Where am i? Class09 --> C2 : Where am i?
Class09 --* C3 Class09 --* C3
Class09 --|> Class07 Class09 --|> Class07
Class12 <|.. Class08 Class12 <|.. Class08
Class11 ..>Class12 Class11 ..>Class12
Class07 : equals() Class07 : equals()
Class07 : Object[] elementData Class07 : Object[] elementData
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class01 : -int privateChimp Class01 : -int privateChimp
Class01 : +int publicGorilla Class01 : +int publicGorilla
Class01 : #int protectedMarmoset Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10 { class Class10 {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
`, `,
{logLevel : 1} {logLevel : 1}
); );
cy.get('svg'); cy.get('svg');
}); });
it('2: should render a simple class diagrams with cardinality', () => { it('2: should render a simple class diagrams with cardinality', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01 &lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04 Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06 Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08 Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i? Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3 Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07 Class09 "1" --|> "1" Class07
Class07 : equals() Class07 : equals()
Class07 : Object[] elementData Class07 : Object[] elementData
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label Class08 "1" <--> "*" C2: Cool label
class Class10 { class Class10 {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('3: should render a simple class diagram with different visibilities', () => { it('3: should render a simple class diagram with different visibilities', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01 <|-- AveryLongClass : Cool Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01 &lt;&lt;interface&gt;&gt; Class01
Class01 : -privateMethod() Class01 : -privateMethod()
Class01 : +publicMethod() Class01 : +publicMethod()
Class01 : #protectedMethod() Class01 : #protectedMethod()
Class01 : -int privateChimp Class01 : -int privateChimp
Class01 : +int publicGorilla Class01 : +int publicGorilla
Class01 : #int protectedMarmoset Class01 : #int protectedMarmoset
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('4: should render a simple class diagram with comments', () => { it('4: should render a simple class diagram with comments', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
%% this is a comment %% this is a comment
Class01 <|-- AveryLongClass : Cool Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01 &lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04 Class03 *-- Class04
Class05 o-- Class06 Class05 o-- Class06
Class07 .. Class08 Class07 .. Class08
Class09 --> C2 : Where am i? Class09 --> C2 : Where am i?
Class09 --* C3 Class09 --* C3
Class09 --|> Class07 Class09 --|> Class07
Class07 : equals() Class07 : equals()
Class07 : Object[] elementData Class07 : Object[] elementData
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10 { class Class10 {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('5: should render a simple class diagram with abstract method', () => { it('5: should render a simple class diagram with abstract method', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01 <|-- AveryLongClass : Cool Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()* Class01 : someMethod()*
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('6: should render a simple class diagram with static method', () => { it('6: should render a simple class diagram with static method', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01 <|-- AveryLongClass : Cool Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()$ Class01 : someMethod()$
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('7: should render a simple class diagram with Generic class', () => { it('7: should render a simple class diagram with Generic class', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class01~T~ class Class01~T~
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10~T~ { class Class10~T~ {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('8: should render a simple class diagram with Generic class and relations', () => { it('8: should render a simple class diagram with Generic class and relations', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01~T~ <|-- AveryLongClass : Cool Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~ Class03~T~ *-- Class04~T~
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10~T~ { class Class10~T~ {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('9: should render a simple class diagram with clickable link', () => { it('9: should render a simple class diagram with clickable link', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01~T~ <|-- AveryLongClass : Cool Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~ Class03~T~ *-- Class04~T~
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10~T~ { class Class10~T~ {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
link Class01 "google.com" "A Tooltip" link Class01 "google.com" "A Tooltip"
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('10: should render a simple class diagram with clickable callback', () => { it('10: should render a simple class diagram with clickable callback', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
Class01~T~ <|-- AveryLongClass : Cool Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~ Class03~T~ *-- Class04~T~
Class01 : size() Class01 : size()
Class01 : int chimp Class01 : int chimp
Class01 : int gorilla Class01 : int gorilla
Class08 <--> C2: Cool label Class08 <--> C2: Cool label
class Class10~T~ { class Class10~T~ {
&lt;&lt;service&gt;&gt; &lt;&lt;service&gt;&gt;
int id int id
test() test()
} }
callback Class01 "functionCall" "A Tooltip" callback Class01 "functionCall" "A Tooltip"
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('11: should render a simple class diagram with return type on method', () => { it('11: should render a simple class diagram with return type on method', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class10~T~ { class Class10~T~ {
int[] id int[] id
test(int[] ids) bool test(int[] ids) bool
testArray() bool[] testArray() bool[]
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('12: should render a simple class diagram with generic types', () => { it('12: should render a simple class diagram with generic types', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class10~T~ { class Class10~T~ {
int[] id int[] id
List~int~ ids List~int~ ids
test(List~int~ ids) List~bool~ test(List~int~ ids) List~bool~
testArray() bool[] testArray() bool[]
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('13: should render a simple class diagram with css classes applied', () => { it('13: should render a simple class diagram with css classes applied', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class10 { class Class10 {
int[] id int[] id
List~int~ ids List~int~ ids
test(List~int~ ids) List~bool~ test(List~int~ ids) List~bool~
testArray() bool[] testArray() bool[]
} }
cssClass "Class10" exClass class Class10:::exClass2
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('14: should render a simple class diagram with css classes applied directly', () => { it('14: should render a simple class diagram with css classes applied directly', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class10:::exClass { class Class10:::exClass2 {
int[] id int[] id
List~int~ ids List~int~ ids
test(List~int~ ids) List~bool~ test(List~int~ ids) List~bool~
testArray() bool[] testArray() bool[]
} }
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
}); });
it('15: should render a simple class diagram with css classes applied two multiple classes', () => { it('15: should render a simple class diagram with css classes applied two multiple classes', () => {
imgSnapshotTest( imgSnapshotTest(
` `
classDiagram classDiagram
class Class10 class Class10
class Class20 class Class20
cssClass "Class10, class20" exClass cssClass "Class10, Class20" exClass2
`, class Class20:::exClass2
{} `,
); {}
cy.get('svg'); );
}); cy.get('svg');
});
it('16: should render multiple class diagrams', () => {
imgSnapshotTest( it('16: should render multiple class diagrams', () => {
[ imgSnapshotTest(
` [
classDiagram `
Class01 "1" <|--|> "*" AveryLongClass : Cool classDiagram
&lt;&lt;interface&gt;&gt; Class01 Class01 "1" <|--|> "*" AveryLongClass : Cool
Class03 "1" *-- "*" Class04 &lt;&lt;interface&gt;&gt; Class01
Class05 "1" o-- "many" Class06 Class03 "1" *-- "*" Class04
Class07 "1" .. "*" Class08 Class05 "1" o-- "many" Class06
Class09 "1" --> "*" C2 : Where am i? Class07 "1" .. "*" Class08
Class09 "*" --* "*" C3 Class09 "1" --> "*" C2 : Where am i?
Class09 "1" --|> "1" Class07 Class09 "*" --* "*" C3
Class07 : equals() Class09 "1" --|> "1" Class07
Class07 : Object[] elementData Class07 : equals()
Class01 : size() Class07 : Object[] elementData
Class01 : int chimp Class01 : size()
Class01 : int gorilla Class01 : int chimp
Class08 "1" <--> "*" C2: Cool label Class01 : int gorilla
class Class10 { Class08 "1" <--> "*" C2: Cool label
&lt;&lt;service&gt;&gt; class Class10 {
int id &lt;&lt;service&gt;&gt;
test() int id
} test()
`, }
` `,
classDiagram `
Class01 "1" <|--|> "*" AveryLongClass : Cool classDiagram
&lt;&lt;interface&gt;&gt; Class01 Class01 "1" <|--|> "*" AveryLongClass : Cool
Class03 "1" *-- "*" Class04 &lt;&lt;interface&gt;&gt; Class01
Class05 "1" o-- "many" Class06 Class03 "1" *-- "*" Class04
Class07 "1" .. "*" Class08 Class05 "1" o-- "many" Class06
Class09 "1" --> "*" C2 : Where am i? Class07 "1" .. "*" Class08
Class09 "*" --* "*" C3 Class09 "1" --> "*" C2 : Where am i?
Class09 "1" --|> "1" Class07 Class09 "*" --* "*" C3
Class07 : equals() Class09 "1" --|> "1" Class07
Class07 : Object[] elementData Class07 : equals()
Class01 : size() Class07 : Object[] elementData
Class01 : int chimp Class01 : size()
Class01 : int gorilla Class01 : int chimp
Class08 "1" <--> "*" C2: Cool label Class01 : int gorilla
class Class10 { Class08 "1" <--> "*" C2: Cool label
&lt;&lt;service&gt;&gt; class Class10 {
int id &lt;&lt;service&gt;&gt;
test() int id
} test()
`, }
], `,
{} ],
); {}
cy.get('svg'); );
}); cy.get('svg');
});
it('17: should render a class diagram when useMaxWidth is true (default)', () => {
renderGraph( // it('17: should render a class diagram when useMaxWidth is true (default)', () => {
` // renderGraph(
classDiagram // `
Class01 <|-- AveryLongClass : Cool // classDiagram
Class01 : size() // Class01 <|-- AveryLongClass : Cool
Class01 : int chimp // Class01 : size()
Class01 : int gorilla // Class01 : int chimp
Class01 : -int privateChimp // Class01 : int gorilla
Class01 : +int publicGorilla // Class01 : -int privateChimp
Class01 : #int protectedMarmoset // Class01 : +int publicGorilla
`, // Class01 : #int protectedMarmoset
{ class: { useMaxWidth: true } } // `,
); // { class: { useMaxWidth: true } }
cy.get('svg') // );
.should((svg) => { // cy.get('svg')
expect(svg).to.have.attr('width', '100%'); // .should((svg) => {
expect(svg).to.have.attr('height', '218'); // expect(svg).to.have.attr('width', '100%');
const style = svg.attr('style'); // const height = parseFloat(svg.attr('height'));
expect(style).to.match(/^max-width: [\d.]+px;$/); // expect(height).to.be.within(332, 333);
const maxWidthValue = parseInt(style.match(/[\d.]+/g).join('')); // // expect(svg).to.have.attr('height', '218');
// use within because the absolute value can be slightly different depending on the environment ±5% // const style = svg.attr('style');
expect(maxWidthValue).to.be.within(160 * .95, 160 * 1.05); // expect(style).to.match(/^max-width: [\d.]+px;$/);
}); // const maxWidthValue = parseInt(style.match(/[\d.]+/g).join(''));
}); // // use within because the absolute value can be slightly different depending on the environment ±5%
// expect(maxWidthValue).to.be.within(203, 204);
it('18: should render a class diagram when useMaxWidth is false', () => { // });
renderGraph( // });
`
classDiagram // it('18: should render a class diagram when useMaxWidth is false', () => {
Class01 <|-- AveryLongClass : Cool // renderGraph(
Class01 : size() // `
Class01 : int chimp // classDiagram
Class01 : int gorilla // Class01 <|-- AveryLongClass : Cool
Class01 : -int privateChimp // Class01 : size()
Class01 : +int publicGorilla // Class01 : int chimp
Class01 : #int protectedMarmoset // Class01 : int gorilla
`, // Class01 : -int privateChimp
{ class: { useMaxWidth: false } } // Class01 : +int publicGorilla
); // Class01 : #int protectedMarmoset
cy.get('svg') // `,
.should((svg) => { // { class: { useMaxWidth: false } }
const width = parseFloat(svg.attr('width')); // );
// use within because the absolute value can be slightly different depending on the environment ±5% // cy.get('svg')
expect(width).to.be.within(160 * .95, 160 * 1.05); // .should((svg) => {
expect(svg).to.have.attr('height', '218'); // const width = parseFloat(svg.attr('width'));
expect(svg).to.not.have.attr('style'); // // use within because the absolute value can be slightly different depending on the environment ±5%
}); // expect(width).to.be.within(100, 101);
}); // const height = parseFloat(svg.attr('height'));
}); // expect(height).to.be.within(332, 333);
// // expect(svg).to.have.attr('height', '332');
// // expect(svg).to.not.have.attr('style');
// });
// });
});

View File

@ -56,7 +56,7 @@ export const insertEdgeLabel = (elem, edge) => {
terminalLabels[edge.id] = {}; terminalLabels[edge.id] = {};
} }
terminalLabels[edge.id].startLeft = startEdgeLabelLeft; terminalLabels[edge.id].startLeft = startEdgeLabelLeft;
setTerminalWidth(fo, bbox); setTerminalWidth(fo, edge.startLabelLeft);
} }
if (edge.startLabelRight) { if (edge.startLabelRight) {
// Create the actual text element // Create the actual text element
@ -72,7 +72,7 @@ export const insertEdgeLabel = (elem, edge) => {
terminalLabels[edge.id] = {}; terminalLabels[edge.id] = {};
} }
terminalLabels[edge.id].startRight = startEdgeLabelRight; terminalLabels[edge.id].startRight = startEdgeLabelRight;
setTerminalWidth(fo, bbox); setTerminalWidth(fo, edge.startLabelRight);
} }
if (edge.endLabelLeft) { if (edge.endLabelLeft) {
// Create the actual text element // Create the actual text element
@ -89,7 +89,7 @@ export const insertEdgeLabel = (elem, edge) => {
terminalLabels[edge.id] = {}; terminalLabels[edge.id] = {};
} }
terminalLabels[edge.id].endLeft = endEdgeLabelLeft; terminalLabels[edge.id].endLeft = endEdgeLabelLeft;
setTerminalWidth(fo, bbox); setTerminalWidth(fo, edge.endLabelLeft);
} }
if (edge.endLabelRight) { if (edge.endLabelRight) {
// Create the actual text element // Create the actual text element
@ -106,14 +106,14 @@ export const insertEdgeLabel = (elem, edge) => {
terminalLabels[edge.id] = {}; terminalLabels[edge.id] = {};
} }
terminalLabels[edge.id].endRight = endEdgeLabelRight; terminalLabels[edge.id].endRight = endEdgeLabelRight;
setTerminalWidth(fo, bbox); setTerminalWidth(fo, edge.endLabelRight);
} }
}; };
function setTerminalWidth(fo, box) { function setTerminalWidth(fo, value) {
if (getConfig().flowchart.htmlLabels && fo) { if (getConfig().flowchart.htmlLabels && fo) {
fo.style.width = box.width; fo.style.width = value.length * 9 + 'px';
fo.style.height = box.height; fo.style.height = '12px';
} }
} }
@ -141,7 +141,7 @@ export const positionEdgeLabel = (edge, paths) => {
let y = edge.y; let y = edge.y;
if (path) { if (path) {
// debugger; // debugger;
const pos = utils.calcTerminalLabelPosition(0, 'start_left', path); const pos = utils.calcTerminalLabelPosition(edge.arrowTypeStart ? 10 : 0, 'start_left', path);
x = pos.x; x = pos.x;
y = pos.y; y = pos.y;
} }
@ -153,7 +153,11 @@ export const positionEdgeLabel = (edge, paths) => {
let y = edge.y; let y = edge.y;
if (path) { if (path) {
// debugger; // debugger;
const pos = utils.calcTerminalLabelPosition(0, 'start_right', path); const pos = utils.calcTerminalLabelPosition(
edge.arrowTypeStart ? 10 : 0,
'start_right',
path
);
x = pos.x; x = pos.x;
y = pos.y; y = pos.y;
} }
@ -165,7 +169,7 @@ export const positionEdgeLabel = (edge, paths) => {
let y = edge.y; let y = edge.y;
if (path) { if (path) {
// debugger; // debugger;
const pos = utils.calcTerminalLabelPosition(0, 'end_left', path); const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_left', path);
x = pos.x; x = pos.x;
y = pos.y; y = pos.y;
} }
@ -177,7 +181,7 @@ export const positionEdgeLabel = (edge, paths) => {
let y = edge.y; let y = edge.y;
if (path) { if (path) {
// debugger; // debugger;
const pos = utils.calcTerminalLabelPosition(0, 'end_right', path); const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_right', path);
x = pos.x; x = pos.x;
y = pos.y; y = pos.y;
} }

View File

@ -900,7 +900,7 @@ top of the chart
* *
* Default value: 'dagre-d3' * Default value: 'dagre-d3'
*/ */
defaultRenderer: 'dagre-d3', defaultRenderer: 'dagre-wrapper',
}, },
git: { git: {
arrowMarkerAbsolute: false, arrowMarkerAbsolute: false,

View File

@ -457,7 +457,7 @@ export const draw = function (text, id) {
rect.setAttribute('ry', 0); rect.setAttribute('ry', 0);
rect.setAttribute('width', dim.width); rect.setAttribute('width', dim.width);
rect.setAttribute('height', dim.height); rect.setAttribute('height', dim.height);
rect.setAttribute('style', 'fill:#e8e8e8;'); // rect.setAttribute('style', 'fill:#e8e8e8;');
label.insertBefore(rect, label.firstChild); label.insertBefore(rect, label.firstChild);
} }

View File

@ -12,6 +12,19 @@ const getStyles = (options) =>
} }
.nodeLabel, .edgeLabel {
color: ${options.classText};
}
.edgeLabel .label rect {
fill: ${options.mainBkg};
}
.label text {
fill: ${options.classText};
}
.edgeLabel .label span {
background: ${options.mainBkg};
}
.classTitle { .classTitle {
font-weight: bolder; font-weight: bolder;
} }

View File

@ -410,7 +410,7 @@ const calcTerminalLabelPosition = (terminalMarkerSize, position, _points) => {
}); });
// Traverse only 25 total distance along points to find cardinality point // Traverse only 25 total distance along points to find cardinality point
const distanceToCardinalityPoint = 25; const distanceToCardinalityPoint = 25 + terminalMarkerSize;
let remainingDistance = distanceToCardinalityPoint; let remainingDistance = distanceToCardinalityPoint;
let center; let center;
@ -437,7 +437,7 @@ const calcTerminalLabelPosition = (terminalMarkerSize, position, _points) => {
prevPoint = point; prevPoint = point;
}); });
// if relation is present (Arrows will be added), change cardinality point off-set distance (d) // if relation is present (Arrows will be added), change cardinality point off-set distance (d)
let d = 10; let d = 10 + terminalMarkerSize * 0.5;
//Calculate Angle for x and y axis //Calculate Angle for x and y axis
let angle = Math.atan2(points[0].y - center.y, points[0].x - center.x); let angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);