-
Notifications
You must be signed in to change notification settings - Fork 18
Add limit violation custom highlighting style support #729
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,17 +11,19 @@ | |
| import com.powsybl.iidm.network.Network; | ||
| import com.powsybl.iidm.network.Terminal; | ||
| import com.powsybl.nad.model.*; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
||
| /** | ||
| * @author Florian Dupuy {@literal <florian.dupuy at rte-france.com>} | ||
| */ | ||
| public class TopologicalStyleProvider extends AbstractVoltageStyleProvider { | ||
|
|
||
| private Map<String, String> limitViolationStyles = Map.of(); | ||
|
|
||
| public TopologicalStyleProvider(Network network) { | ||
| super(network); | ||
| } | ||
|
|
@@ -30,11 +32,34 @@ public TopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltageS | |
| super(network, baseVoltageStyle); | ||
| } | ||
|
|
||
| public TopologicalStyleProvider(Network network, Map<String, String> limitViolationStyles) { | ||
| super(network); | ||
| this.limitViolationStyles = limitViolationStyles; | ||
| } | ||
|
|
||
| public TopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltageStyle, Map<String, String> limitViolationStyles) { | ||
| super(network, baseVoltageStyle); | ||
| this.limitViolationStyles = limitViolationStyles; | ||
| } | ||
|
|
||
| @Override | ||
| public List<String> getCssFilenames() { | ||
| return Collections.singletonList("topologicalStyle.css"); | ||
| } | ||
|
|
||
| @Override | ||
| public List<String> getBranchEdgeStyleClasses(BranchEdge branchEdge) { | ||
| // Check custom violations first | ||
| if (!limitViolationStyles.isEmpty()) { | ||
| String customStyle = limitViolationStyles.get(branchEdge.getEquipmentId()); | ||
| if (customStyle != null && !customStyle.isBlank()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| return List.of(customStyle); | ||
| } | ||
| } | ||
| // Fallback to default overload detection | ||
| return super.getBranchEdgeStyleClasses(branchEdge); | ||
| } | ||
|
|
||
| @Override | ||
| public List<String> getBusNodeStyleClasses(BusNode busNode) { | ||
| List<String> styles = new ArrayList<>(super.getBusNodeStyleClasses(busNode)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ | ||
| package com.powsybl.nad.svg.iidm; | ||
|
|
||
| import com.powsybl.commons.config.BaseVoltagesConfig; | ||
| import com.powsybl.diagram.test.Networks; | ||
| import com.powsybl.iidm.network.Network; | ||
| import com.powsybl.iidm.network.Terminal; | ||
| import com.powsybl.nad.model.BranchEdge; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
|
||
| class TopologicalStyleProviderTest { | ||
|
|
||
| @Test | ||
| void customLimitViolationStyleOverridesDefaultBranchStyle() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| TopologicalStyleProvider provider = new TopologicalStyleProvider(network, Map.of("Line", "custom-style")); | ||
| BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); | ||
|
|
||
| List<String> styles = provider.getBranchEdgeStyleClasses(branchEdge); | ||
|
|
||
| assertEquals(List.of("custom-style"), styles); | ||
| } | ||
|
|
||
| @Test | ||
| void missingCustomStyleFallsBackToDefaultBranchStyle() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); | ||
|
|
||
| TopologicalStyleProvider defaultProvider = new TopologicalStyleProvider(network); | ||
| List<String> defaultStyles = defaultProvider.getBranchEdgeStyleClasses(branchEdge); | ||
|
|
||
| TopologicalStyleProvider providerWithCustomMap = new TopologicalStyleProvider(network, Map.of("OtherLine", "custom-style")); | ||
| List<String> styles = providerWithCustomMap.getBranchEdgeStyleClasses(branchEdge); | ||
|
|
||
| assertEquals(defaultStyles, styles); | ||
| } | ||
|
|
||
| @Test | ||
| void constructorWithBaseVoltageConfigKeepsCustomStyles() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| BaseVoltagesConfig baseVoltagesConfig = BaseVoltagesConfig.fromPlatformConfig(); | ||
| BranchEdge branchEdge = new BranchEdge("diagram", "Line", "Line", BranchEdge.LINE_EDGE); | ||
|
|
||
| TopologicalStyleProvider provider = new TopologicalStyleProvider(network, baseVoltagesConfig, Map.of("Line", "custom-style")); | ||
|
|
||
| assertEquals(List.of("custom-style"), provider.getBranchEdgeStyleClasses(branchEdge)); | ||
| } | ||
|
|
||
| @Test | ||
| void baseVoltageStyleReturnsEmptyForNullTerminal() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| BaseVoltagesConfig baseVoltagesConfig = BaseVoltagesConfig.fromPlatformConfig(); | ||
| TestTopologicalStyleProvider provider = new TestTopologicalStyleProvider(network, baseVoltagesConfig); | ||
|
|
||
| assertTrue(provider.getBaseVoltageStyleForTerminal(null).isEmpty()); | ||
| } | ||
|
|
||
| private static final class TestTopologicalStyleProvider extends TopologicalStyleProvider { | ||
|
|
||
| private TestTopologicalStyleProvider(Network network, BaseVoltagesConfig baseVoltagesConfig) { | ||
| super(network, baseVoltagesConfig); | ||
| } | ||
|
|
||
| private Optional<String> getBaseVoltageStyleForTerminal(Terminal terminal) { | ||
| return super.getBaseVoltageStyle(terminal); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,17 +22,43 @@ | |
| */ | ||
| public class LimitHighlightStyleProvider extends EmptyStyleProvider { | ||
| private final Network network; | ||
| private Map<String, String> limitViolationStyles = Map.of(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's a problem here, there's nothing which links these styles to limit violations here. Why didn't you include the logic which gives a style to a specific violation limit in this class? Similarly to isOverloaded method. |
||
|
|
||
| public LimitHighlightStyleProvider(Network network) { | ||
| this(network, Collections.emptyMap()); | ||
ayolab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| public LimitHighlightStyleProvider(Network network, Map<String, String> limitViolationStyles) { | ||
| this.network = network; | ||
| this.limitViolationStyles = limitViolationStyles; | ||
| } | ||
|
|
||
| @Override | ||
| public List<String> getEdgeStyles(Graph graph, Edge edge) { | ||
| // Check custom violations first | ||
| if (!limitViolationStyles.isEmpty()) { | ||
| Optional<String> customStyle = getCustomViolationStyle(edge); | ||
| if (customStyle.isPresent()) { | ||
| return List.of(customStyle.get()); | ||
| } | ||
| } | ||
| // Fallback to default overload detection | ||
| Optional<String> overloadStyle = getOverloadStyle(edge); | ||
| return overloadStyle.map(Collections::singletonList).orElse(Collections.emptyList()); | ||
| } | ||
|
|
||
| private Optional<String> getCustomViolationStyle(Edge edge) { | ||
| for (Node node : edge.getNodes()) { | ||
| if (node instanceof FeederNode feederNode) { | ||
| String style = limitViolationStyles.get(feederNode.getEquipmentId()); | ||
| if (style != null && !style.isBlank()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. StringUtils.isBlank() ? |
||
| return Optional.of(style); | ||
| } | ||
| } | ||
| } | ||
| return Optional.empty(); | ||
| } | ||
|
|
||
| private Optional<String> getOverloadStyle(Edge edge) { | ||
| List<Node> nodes = edge.getNodes(); | ||
| for (Node node : nodes) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /** | ||
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ | ||
| package com.powsybl.sld.svg.styles.iidm; | ||
|
|
||
| import com.powsybl.diagram.test.Networks; | ||
| import com.powsybl.iidm.network.Network; | ||
| import com.powsybl.sld.model.graphs.VoltageLevelInfos; | ||
| import com.powsybl.sld.model.nodes.BusNode; | ||
| import com.powsybl.sld.model.nodes.Edge; | ||
| import com.powsybl.sld.model.nodes.FeederNode; | ||
| import com.powsybl.sld.model.nodes.FeederType; | ||
| import com.powsybl.sld.model.nodes.NodeSide; | ||
| import com.powsybl.sld.model.nodes.feeders.FeederWithSides; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
||
| class LimitHighlightStyleProviderTest { | ||
|
|
||
| private static Edge buildEdge(String equipmentId) { | ||
| FeederWithSides feeder = new FeederWithSides( | ||
| FeederType.BRANCH, | ||
| NodeSide.ONE, | ||
| new VoltageLevelInfos("VL1", "VoltageLevel1", 225.0), | ||
| new VoltageLevelInfos("VL2", "VoltageLevel2", 225.0) | ||
| ); | ||
| FeederNode feederNode = new FeederNode("feederNode", "Feeder", equipmentId, "component", false, feeder, null); | ||
| BusNode busNode = new BusNode("busNode", "Bus", false); | ||
| return new Edge(feederNode, busNode); | ||
| } | ||
|
|
||
| @Test | ||
| void customLimitViolationStyleOverridesDefaultEdgeStyles() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| LimitHighlightStyleProvider provider = new LimitHighlightStyleProvider(network, Map.of("Line", "custom-style")); | ||
| Edge edge = buildEdge("Line"); | ||
|
|
||
| List<String> styles = provider.getEdgeStyles(null, edge); | ||
|
|
||
| assertEquals(List.of("custom-style"), styles); | ||
| } | ||
|
|
||
| @Test | ||
| void missingCustomStyleFallsBackToDefaultEdgeStyles() { | ||
| Network network = Networks.createNetworkWithLine(); | ||
| Edge edge = buildEdge("Line"); | ||
|
|
||
| LimitHighlightStyleProvider defaultProvider = new LimitHighlightStyleProvider(network); | ||
| List<String> defaultStyles = defaultProvider.getEdgeStyles(null, edge); | ||
|
|
||
| LimitHighlightStyleProvider providerWithCustomMap = new LimitHighlightStyleProvider(network, Map.of("OtherLine", "custom-style")); | ||
| List<String> styles = providerWithCustomMap.getEdgeStyles(null, edge); | ||
|
|
||
| assertEquals(defaultStyles, styles); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
limitViolationStylesByBranchId?