Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demo/nad-created.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ <h2>Network Area Diagram SVGs created from diagram metadata</h2>
<figcaption>Edge info with double arrows from metadata</figcaption>
<div id="svg-container-nad-double-arrows-c"></div>
</figure>
<div class="break"></div>
<figure class="diagram-figure">
<figcaption>Custom style provider</figcaption>
<div id="svg-container-nad-pst-hvdc-custom"></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ import { HalfEdge, LabelData } from './diagram-types';
export class EdgeRouter {
diagramMetadata: DiagramMetadata;
svgParameters: SvgParameters;
// points of each half edge of edges
edgePoints: Record<string, [Point[], Point[]]> = {};
// data (position and arrow angle) for side infos of each half edge of edges
edgeSideData: Record<string, [[Point, number], [Point, number]]> = {};
// label data (angle, internal and external shift and style) for side infos of each half edge of edges
edgeSideLabelData: Record<string, [LabelData, LabelData]> = {};
// data (position and arrow angle) for middle infos of edges
edgeMiddleData: Record<string, [Point, number]> = {};
// label data (angle, internal and external shift and style) for middle infos of edges
edgeMiddleLabelData: Record<string, LabelData> = {};
// points of 3wt edges
threeWTEdgePoints: Record<string, [Point, Point]> = {};
nodeAngles: Record<string, number[]> = {};

Expand Down Expand Up @@ -176,29 +182,32 @@ export class EdgeRouter {
const node2Angles: number[] = this.nodeAngles[edge.node2] ?? [];
node2Angles.push(angle2);
this.nodeAngles[edge.node2] = node2Angles;
this.storeEdgeInfos(edge, halfEdges);
this.storeEdgeInfos(edge, halfEdges, false);
}

private storeEdgeInfos(edge: EdgeMetadata, halfEdges: HalfEdge[] | null[]) {
private storeEdgeInfos(edge: EdgeMetadata, halfEdges: HalfEdge[] | null[], isLoop: boolean) {
if (edge.edgeInfo1 || edge.edgeInfo2) {
this.storeEdgeSideData(edge.svgId, halfEdges);
this.storeEdgeSideData(edge.svgId, halfEdges, isLoop);
}
if (edge.edgeInfoMiddle) {
this.storeEdgeMiddleData(edge.svgId, halfEdges);
}
}

private storeEdgeSideData(edgeId: string, halfEdges: HalfEdge[] | null[]) {
// given an edge id and 2 half edges, store data for edge side infos
// the isLoop parameter is needed because the computation of the position of edge side info
// is different if we are dealing with loop edges
private storeEdgeSideData(edgeId: string, halfEdges: HalfEdge[] | null[], isLoop: boolean) {
Comment thread
NathanDissoubray marked this conversation as resolved.
if (!halfEdges[0] || !halfEdges[1]) {
return;
}
this.edgeSideData[edgeId] = [
[
HalfEdgeUtils.getInfoPoint(halfEdges[0], this.svgParameters),
isLoop ? halfEdges[0].edgePoints[1] : HalfEdgeUtils.getInfoPoint(halfEdges[0], this.svgParameters),
HalfEdgeUtils.getArrowRotation(halfEdges[0]),
],
[
HalfEdgeUtils.getInfoPoint(halfEdges[1], this.svgParameters),
isLoop ? halfEdges[1].edgePoints[1] : HalfEdgeUtils.getInfoPoint(halfEdges[1], this.svgParameters),
Comment thread
NathanDissoubray marked this conversation as resolved.
HalfEdgeUtils.getArrowRotation(halfEdges[1]),
],
];
Expand Down Expand Up @@ -366,7 +375,7 @@ export class EdgeRouter {
return;
}
this.edgePoints[edge.svgId] = [halfEdges[0].edgePoints, halfEdges[1].edgePoints];
this.storeEdgeInfos(edge, halfEdges);
this.storeEdgeInfos(edge, halfEdges, true);
}

private storeThreeWtEdges(edgesMap: Record<string, EdgeMetadata[]>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,20 +494,22 @@ test('getHalfEdges', () => {
expect(halfEdges[0]).not.toBeNull();
if (halfEdges[0]) {
expect(halfEdges[0].edgePoints.length).toBe(3);
expect(round(halfEdges[0].edgePoints[0].x)).toBeCloseTo(-220.63);
expect(round(halfEdges[0].edgePoints[0].y)).toBeCloseTo(22.08);
expect(round(halfEdges[0].edgePoints[1].x)).toBeCloseTo(-173.6);
expect(round(halfEdges[0].edgePoints[1].y)).toBeCloseTo(-1.26);
expect(halfEdges[0].side).toBe('1');
expect(round(halfEdges[0].edgePoints[0].x)).toBeCloseTo(117.43);
expect(round(halfEdges[0].edgePoints[0].y)).toBeCloseTo(43.39);
expect(round(halfEdges[0].edgePoints[1].x)).toBeCloseTo(73.7);
expect(round(halfEdges[0].edgePoints[1].y)).toBeCloseTo(14.33);
expect(round(halfEdges[0].edgePoints[2].x)).toBeCloseTo(-49.95);
expect(round(halfEdges[0].edgePoints[2].y)).toBeCloseTo(6.53);
}
expect(halfEdges[1]).not.toBeNull();
if (halfEdges[1]) {
expect(halfEdges[1].edgePoints.length).toBe(3);
expect(round(halfEdges[1].edgePoints[0].x)).toBeCloseTo(117.43);
expect(round(halfEdges[1].edgePoints[0].y)).toBeCloseTo(43.39);
expect(round(halfEdges[1].edgePoints[1].x)).toBeCloseTo(73.7);
expect(round(halfEdges[1].edgePoints[1].y)).toBeCloseTo(14.33);
expect(halfEdges[1].side).toBe('2');
expect(round(halfEdges[1].edgePoints[0].x)).toBeCloseTo(-220.63);
expect(round(halfEdges[1].edgePoints[0].y)).toBeCloseTo(22.08);
expect(round(halfEdges[1].edgePoints[1].x)).toBeCloseTo(-173.6);
expect(round(halfEdges[1].edgePoints[1].y)).toBeCloseTo(-1.26);
expect(round(halfEdges[1].edgePoints[2].x)).toBeCloseTo(-49.95);
expect(round(halfEdges[1].edgePoints[2].y)).toBeCloseTo(6.53);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ import {
isTransformerEdge,
radToDeg,
} from './diagram-utils';
import { getBusNodeMetadata, getEdgePoints, getEdgeType, getNodeMetadata, getNodeRadius } from './metadata-utils';
import {
getBusNodeMetadata,
getEdgePoints,
getEdgeType,
getNodeMetadata,
getNodeRadius,
samePosition,
} from './metadata-utils';
import { HalfEdge, LabelData } from './diagram-types';
import { getPathPoints, getTransform } from './svg-utils';

Expand Down Expand Up @@ -278,22 +285,22 @@ export function getHalfEdges(
edge.bendingPoints
);
const halfEdge1: HalfEdge = {
side: '1',
side: samePosition(node1, point1) ? '1' : '2',
fork: groupedEdgesCount > 1,
busOuterRadius: nodeRadius1.busOuterRadius,
voltageLevelRadius: nodeRadius1.voltageLevelRadius,
edgeInfoId: edge.edgeInfo1?.svgId,
edgePoints: edgePoints[0],
};
const halfEdge2: HalfEdge = {
side: '2',
side: samePosition(node2, point2) ? '2' : '1',
fork: groupedEdgesCount > 1,
busOuterRadius: nodeRadius2.busOuterRadius,
voltageLevelRadius: nodeRadius2.voltageLevelRadius,
edgeInfoId: edge.edgeInfo2?.svgId,
edgePoints: edgePoints[1],
};
return [halfEdge1, halfEdge2];
return [samePosition(node1, point1) ? halfEdge1 : halfEdge2, samePosition(node2, point2) ? halfEdge2 : halfEdge1];
}

export function getHalfEdgesLoop(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,3 +594,16 @@ test('getEdgeType', () => {
expect(MetadataUtils.getEdgeType(edge)).toBe(EdgeType.TWO_WINDINGS_TRANSFORMER);
expect(MetadataUtils.getStringEdgeType(edge)).toBe('TWO_WINDINGS_TRANSFORMER');
});

test('samePosition', () => {
const node: NodeMetadata = {
svgId: '4',
equipmentId: 'VL',
x: 100,
y: 100,
};
expect(MetadataUtils.samePosition(node, new Point(100, 100))).toBe(true);
expect(MetadataUtils.samePosition(node, new Point(90, 100))).toBe(false);
expect(MetadataUtils.samePosition(node, new Point(100, 90))).toBe(false);
expect(MetadataUtils.samePosition(node, new Point(90, 90))).toBe(false);
});
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,7 @@ export function isBoundaryNode(node: NodeMetadata): boolean {
export function getNodeType(node: NodeMetadata): NodeType {
return node.type === undefined ? NodeType.UNKNOWN : (NodeTypeMapping[node.type] ?? NodeType.UNKNOWN);
}

export function samePosition(node: NodeMetadata, point: Point): boolean {
return point.x == node.x && point.y == node.y;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@
*/

import '../../../../global.d.ts';
import IEE14CdfNetworkMetadata from '../resources/test-data/nad-ieee14cdf-solved_metadata.json';

import IEEE14CdfNetworkMetadata from '../resources/test-data/nad-ieee14cdf-solved_metadata.json';
import FourSubstationsNetworkCustomStyleMetadata from '../resources/test-data/nad-four-substations_custom_metadata.json';
import EurostagNetworkMetadata from '../resources/test-data/nad-eurostag-tutorial-example1_metadata.json';
import IEEE9NetworkMetadata from '../resources/test-data/nad-ieee9-zeroimpedance-cdf_metadata.json';
import FourSubstationsNetworkMetadata from '../resources/test-data/nad-four-substations_metadata.json';
import IEEE9NetworkMiddleArrowsMetadata from '../resources/test-data/nad-ieee9-zeroimpedance-cdf-middle-arrow_metadata.json';
import FourSubstationsNetworkMultipleLabelsMetadata from '../resources/test-data/nad-four-substations-multiple-labels_metadata.json';
import DoubleArrowsNetworkMetadata from '../resources/test-data/nad-double-arrows-with-middle-values_metadata.json';

import { SvgWriter } from './svg-writer';
import { getSvgFromFile } from './test-utils';

test('testIEE14CdfNetwork', () => {
const actual = new SvgWriter(IEE14CdfNetworkMetadata).getSvg({ width: 0, height: 0 });
test('testIEEE14CdfNetwork', () => {
const actual = new SvgWriter(IEEE14CdfNetworkMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-ieee14cdf-solved.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});
Expand All @@ -24,3 +31,39 @@ test('testFourSubstationsNetworkCustomStyle', () => {
const expected = getSvgFromFile('../resources/test-data/nad-four-substations_custom.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testEurostagNetwork', () => {
const actual = new SvgWriter(EurostagNetworkMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-eurostag-tutorial-example1.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testIEEE9Network', () => {
const actual = new SvgWriter(IEEE9NetworkMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-ieee9-zeroimpedance-cdf.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testFourSubstationsNetwork', () => {
const actual = new SvgWriter(FourSubstationsNetworkMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-four-substations.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testIEEE9NetworkMiddleArrows', () => {
const actual = new SvgWriter(IEEE9NetworkMiddleArrowsMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-ieee9-zeroimpedance-cdf-middle-arrow.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testFourSubstationsNetworkMultipleLabelsNetwork', () => {
const actual = new SvgWriter(FourSubstationsNetworkMultipleLabelsMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-four-substations-multiple-labels.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});

test('testDoubleArrowsNetwork', () => {
const actual = new SvgWriter(DoubleArrowsNetworkMetadata).getSvg({ width: 0, height: 0 });
const expected = getSvgFromFile('../resources/test-data/nad-double-arrows-with-middle-values.svg');
expect(actual).toEqualSvg(expected, { epsilon: 0.1 });
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading