Skip to content

Commit a754257

Browse files
authored
Merge branch 'main' into 672-3wt-phase-tap-changer
2 parents 88f301f + 4162edf commit a754257

6 files changed

Lines changed: 808 additions & 2 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package com.powsybl.nad.svg;
9+
10+
import com.powsybl.nad.model.*;
11+
import com.powsybl.nad.utils.svg.SvgUtils;
12+
13+
import java.util.*;
14+
15+
/**
16+
* Enables the configuration of content displayed in the NAD for branches and three-winding-transformers (labels, arrows direction),
17+
* and VL info boxes (voltage levels and buses labels).
18+
* <p>
19+
* Customizations are defined in the constructor's map parameters.
20+
*
21+
* <p>
22+
* The branchLabels map defines what will be displayed on the branches, and it is indexed by branch ID.
23+
* The custom content is declared via the BranchLabels record: side1 and side2 are the labels displayed on the edges of a branch,
24+
* while middle is the label displayed halfway along the branch.
25+
* Arrow1 and arrow2 determine the direction of the arrows displayed on the edges.
26+
*
27+
* <p>
28+
* The threeWtLabels map defines what will be displayed on the three-winding-transformers legs, and it is indexed by the equipment ID.
29+
* The custom content is declared via the ThreeWtLabels record: side1, side2, and side3 are the labels to be displayed on the respective transformer's legs.
30+
* Similarly, arrow1, arrow2, and arrow3 determine the direction of the arrows displayed on the respective transformer's legs.
31+
*
32+
* <p>
33+
* The busDescriptions map is indexed by the ID of the bus (in the bus view) and allows to set a bus's label, displayed in the VL info box central section.
34+
*
35+
* <p>
36+
* VlDescriptions and vlDetails maps, indexed by the voltage level ID, define the VL related content found in the VL info boxes.
37+
* VlDescriptions data will be displayed in the VL info box top section, while vlDetails will be displayed in the bottom section.
38+
* For each ID, the maps contain a list of strings that will be displayed sequentially, following the implicit order of the list.
39+
*
40+
* @author Christian Biasuzzi {@literal <christian.biasuzzi at soft.it>}
41+
*/
42+
public class CustomLabelProvider implements LabelProvider {
43+
final Map<String, BranchLabels> branchLabels;
44+
final Map<String, ThreeWtLabels> threeWtLabels;
45+
final Map<String, String> busDescriptions;
46+
final Map<String, List<String>> vlDescriptions;
47+
final Map<String, List<String>> vlDetails;
48+
49+
public record BranchLabels(String side1, String middle, String side2, EdgeInfo.Direction arrow1, EdgeInfo.Direction arrow2) {
50+
}
51+
52+
public record ThreeWtLabels(String side1, String side2, String side3, EdgeInfo.Direction arrow1, EdgeInfo.Direction arrow2, EdgeInfo.Direction arrow3) {
53+
}
54+
55+
public CustomLabelProvider(Map<String, BranchLabels> branchLabels, Map<String, ThreeWtLabels> threeWtLabels,
56+
Map<String, String> busDescriptions, Map<String, List<String>> vlDescriptions, Map<String, List<String>> vlDetails) {
57+
this.branchLabels = Objects.requireNonNull(branchLabels);
58+
this.threeWtLabels = Objects.requireNonNull(threeWtLabels);
59+
this.busDescriptions = Objects.requireNonNull(busDescriptions);
60+
this.vlDescriptions = Objects.requireNonNull(vlDescriptions);
61+
this.vlDetails = Objects.requireNonNull(vlDetails);
62+
}
63+
64+
@Override
65+
public Optional<EdgeInfo> getEdgeInfo(Graph graph, BranchEdge edge, BranchEdge.Side side) {
66+
BranchLabels bl = this.branchLabels.get(edge.getEquipmentId());
67+
String label = null;
68+
EdgeInfo.Direction arrowDirection = null;
69+
if (bl != null) {
70+
label = side == BranchEdge.Side.ONE ? bl.side1 : bl.side2;
71+
arrowDirection = side == BranchEdge.Side.ONE ? bl.arrow1 : bl.arrow2;
72+
}
73+
return Optional.of(new EdgeInfo("Custom", arrowDirection, null, label));
74+
}
75+
76+
@Override
77+
public Optional<EdgeInfo> getEdgeInfo(Graph graph, ThreeWtEdge edge) {
78+
ThreeWtLabels threeWtLabels1 = threeWtLabels.get(edge.getEquipmentId());
79+
ThreeWtEdge.Side edgeSide = edge.getSide();
80+
String labelSide = null;
81+
EdgeInfo.Direction arrowDirection = null;
82+
if (threeWtLabels1 != null) {
83+
switch (edgeSide) {
84+
case ONE -> {
85+
labelSide = threeWtLabels1.side1;
86+
arrowDirection = threeWtLabels1.arrow1;
87+
}
88+
case TWO -> {
89+
labelSide = threeWtLabels1.side2;
90+
arrowDirection = threeWtLabels1.arrow2;
91+
}
92+
case THREE -> {
93+
labelSide = threeWtLabels1.side3;
94+
arrowDirection = threeWtLabels1.arrow3;
95+
}
96+
}
97+
}
98+
return Optional.of(new EdgeInfo("Custom", arrowDirection, null, labelSide));
99+
}
100+
101+
@Override
102+
public String getLabel(Edge edge) {
103+
BranchLabels bl = branchLabels.get(edge.getEquipmentId());
104+
return (bl != null) ? bl.middle : null;
105+
}
106+
107+
@Override
108+
public String getBusDescription(BusNode busNode) {
109+
return busDescriptions.get(busNode.getEquipmentId());
110+
}
111+
112+
@Override
113+
public List<String> getVoltageLevelDescription(VoltageLevelNode voltageLevelNode) {
114+
return vlDescriptions.getOrDefault(voltageLevelNode.getEquipmentId(), Collections.emptyList());
115+
}
116+
117+
@Override
118+
public List<String> getVoltageLevelDetails(VoltageLevelNode vlNode) {
119+
return vlDetails.getOrDefault(vlNode.getEquipmentId(), Collections.emptyList());
120+
}
121+
122+
@Override
123+
public String getArrowPathDIn() {
124+
return SvgUtils.ARROW_PATH_DIN;
125+
}
126+
127+
@Override
128+
public String getArrowPathDOut() {
129+
return SvgUtils.ARROW_PATH_DOUT;
130+
}
131+
}

network-area-diagram/src/main/java/com/powsybl/nad/svg/iidm/DefaultLabelProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.powsybl.nad.svg.LabelProvider;
1515
import com.powsybl.nad.svg.SvgParameters;
1616
import com.powsybl.nad.utils.iidm.IidmUtils;
17+
import com.powsybl.nad.utils.svg.SvgUtils;
1718

1819
import java.util.ArrayList;
1920
import java.util.List;
@@ -121,11 +122,11 @@ public List<String> getVoltageLevelDetails(VoltageLevelNode vlNode) {
121122

122123
@Override
123124
public String getArrowPathDIn() {
124-
return "M-1 -1 H1 L0 1z";
125+
return SvgUtils.ARROW_PATH_DIN;
125126
}
126127

127128
@Override
128129
public String getArrowPathDOut() {
129-
return "M-1 1 H1 L0 -1z";
130+
return SvgUtils.ARROW_PATH_DOUT;
130131
}
131132
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package com.powsybl.nad.utils.svg;
8+
9+
/**
10+
* @author Christian Biasuzzi {@literal <christian.biasuzzi at soft.it>}
11+
*/
12+
public final class SvgUtils {
13+
14+
private SvgUtils() {
15+
}
16+
17+
public static final String ARROW_PATH_DIN = "M-1 -1 H1 L0 1z";
18+
19+
public static final String ARROW_PATH_DOUT = "M-1 1 H1 L0 -1z";
20+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package com.powsybl.nad.svg;
9+
10+
import com.powsybl.diagram.test.Networks;
11+
import com.powsybl.iidm.network.Network;
12+
import com.powsybl.iidm.network.test.ThreeWindingsTransformerNetworkFactory;
13+
import com.powsybl.nad.AbstractTest;
14+
import com.powsybl.nad.layout.LayoutParameters;
15+
import com.powsybl.nad.svg.iidm.TopologicalStyleProvider;
16+
import org.junit.jupiter.api.BeforeEach;
17+
import org.junit.jupiter.api.Test;
18+
19+
import java.util.HashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
/**
24+
* @author Christian Biasuzzi {@literal <christian.biasuzzi at soft.it>}
25+
*/
26+
class CustomLabelProviderTest extends AbstractTest {
27+
28+
LabelProvider labelProvider;
29+
30+
@BeforeEach
31+
void setup() {
32+
setLayoutParameters(new LayoutParameters());
33+
34+
//Note: SvgParameters EdgeNameDisplayed, VoltageLevelDetails, and BusLegend must be true,
35+
// for the edge names, the VL descriptions plus VL details, and bus descriptions to be rendered
36+
setSvgParameters(new SvgParameters()
37+
.setSvgWidthAndHeightAdded(true)
38+
.setFixedWidth(800)
39+
.setEdgeNameDisplayed(true)
40+
.setVoltageLevelDetails(true)
41+
.setBusLegend(true));
42+
}
43+
44+
@Override
45+
protected StyleProvider getStyleProvider(Network network) {
46+
return new TopologicalStyleProvider(network);
47+
}
48+
49+
@Override
50+
protected LabelProvider getLabelProvider(Network network) {
51+
return labelProvider;
52+
}
53+
54+
@Test
55+
void testCustomLabelProvider() {
56+
Network network = Networks.createNodeBreakerNetworkWithBranchStatus("TestNodeDecorators", "test");
57+
58+
Map<String, CustomLabelProvider.BranchLabels> branchLabels = new HashMap<>();
59+
branchLabels.put("L12", new CustomLabelProvider.BranchLabels("L1_1", "L1", "L1_2", EdgeInfo.Direction.IN, EdgeInfo.Direction.IN));
60+
branchLabels.put("T12", new CustomLabelProvider.BranchLabels("TWT1_1", "TWT1", "TWT1_2", null, null));
61+
branchLabels.put("L11", new CustomLabelProvider.BranchLabels(null, "L2", null, EdgeInfo.Direction.IN, EdgeInfo.Direction.IN));
62+
branchLabels.put("T11", new CustomLabelProvider.BranchLabels(null, "TWT2", "TWT2_2", null, EdgeInfo.Direction.OUT));
63+
64+
Map<String, CustomLabelProvider.ThreeWtLabels> threeWtLabels = new HashMap<>();
65+
66+
Map<String, String> busDescriptions = new HashMap<>();
67+
busDescriptions.put("VL1_10", "VL1 10");
68+
busDescriptions.put("VL2_30", "VL2 30");
69+
70+
Map<String, List<String>> vlDescriptions = new HashMap<>();
71+
vlDescriptions.put("VL1", List.of("VL1 description1", "VL1 description2"));
72+
vlDescriptions.put("VL2", List.of("VL2 description1"));
73+
74+
Map<String, List<String>> vlDetails = new HashMap<>();
75+
vlDetails.put("VL2", List.of("VL2 details1", "VL2 details2"));
76+
77+
labelProvider = new CustomLabelProvider(branchLabels, threeWtLabels, busDescriptions, vlDescriptions, vlDetails);
78+
79+
assertSvgEquals("/custom_label_provider.svg", network);
80+
}
81+
82+
@Test
83+
void testCustomLabelProvider3wt() {
84+
Network network = ThreeWindingsTransformerNetworkFactory.create();
85+
86+
Map<String, CustomLabelProvider.BranchLabels> branchLabels = new HashMap<>();
87+
Map<String, CustomLabelProvider.ThreeWtLabels> threeWtLabels = new HashMap<>();
88+
threeWtLabels.put("3WT", new CustomLabelProvider.ThreeWtLabels("SIDE1", "SIDE2", "SIDE3", EdgeInfo.Direction.IN, EdgeInfo.Direction.OUT, EdgeInfo.Direction.IN));
89+
90+
Map<String, String> busDescriptions = new HashMap<>();
91+
busDescriptions.put("VL_132_0", "VL1 132");
92+
busDescriptions.put("VL_33_0", "VL2 33");
93+
busDescriptions.put("VL_11_0", "VL2 11");
94+
95+
Map<String, List<String>> vlDescriptions = new HashMap<>();
96+
vlDescriptions.put("VL_132", List.of("VL 132 description1", "VL1 132 description2"));
97+
vlDescriptions.put("VL_33", List.of("VL 33 description1"));
98+
vlDescriptions.put("VL_11", List.of("VL 11 description1"));
99+
100+
Map<String, List<String>> vlDetails = new HashMap<>();
101+
vlDetails.put("VL_132", List.of("VL 132 details1"));
102+
vlDetails.put("VL_33", List.of("VL 33 details1", "VL 33 details2"));
103+
vlDetails.put("VL_11", List.of("VL 1 details1"));
104+
105+
labelProvider = new CustomLabelProvider(branchLabels, threeWtLabels, busDescriptions, vlDescriptions, vlDetails);
106+
107+
assertSvgEquals("/custom_label_provider_3wt.svg", network);
108+
}
109+
110+
}

0 commit comments

Comments
 (0)