Skip to content
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

Size and grid fitting cells #347

Merged
merged 10 commits into from
Feb 21, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -547,4 +547,11 @@ public double getBottom() {
return bottom;
}
}

@JsonIgnore
public double getFeederSpan() {
// The space needed between the feeder and the node connected to it corresponds to the space for feeder arrows
// + half the height of the feeder component + half the height of that node component
return getSpaceForFeederInfos() + getMaxComponentHeight();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author Benoit Jeanson <benoit.jeanson at rte-france.com>
Expand All @@ -37,7 +36,7 @@ public PositionVoltageLevelLayout(VoltageLevelGraph graph) {
@Override
public void run(LayoutParameters layoutParam) {
LOGGER.info("Running voltage level layout");
calculateExternCellHeight(layoutParam);
calculateMaxCellHeight(layoutParam);
calculateBusNodeCoord(getGraph(), layoutParam);
calculateCellCoord(getGraph(), layoutParam);

Expand All @@ -63,7 +62,7 @@ private void setGraphSize(LayoutParameters layoutParam) {
double elementaryWidth = layoutParam.getCellWidth() / 2; // the elementary step within a voltageLevel Graph is half a cell width
double widthWithoutPadding = graph.getMaxH() * elementaryWidth;
double heightWithoutPadding = graph.getExternCellHeight(BusCell.Direction.TOP)
+ 2 * layoutParam.getStackHeight() + layoutParam.getVerticalSpaceBus() * graph.getMaxV()
+ layoutParam.getVerticalSpaceBus() * graph.getMaxV()
+ graph.getExternCellHeight(BusCell.Direction.BOTTOM);

LayoutParameters.Padding padding = layoutParam.getVoltageLevelPadding();
Expand Down Expand Up @@ -102,33 +101,43 @@ private void calculateCellCoord(VoltageLevelGraph graph, LayoutParameters layout
}

/**
* Calculating the maximum height of all the extern cells in each direction (top and bottom). This height does not
* include the constant stack height.
* Calculating the maximum height of all the extern cells in each direction (top and bottom).
* If no extern cell found taking into account intern cells too.
* This height does include the constant stack height.
* @param layoutParam the layout parameters
*/
private void calculateExternCellHeight(LayoutParameters layoutParam) {
Map<BusCell.Direction, Double> maxCellHeight = EnumSet.allOf(BusCell.Direction.class).stream().collect(Collectors.toMap(Function.identity(), v -> 0.));
private void calculateMaxCellHeight(LayoutParameters layoutParam) {
Map<BusCell.Direction, Double> maxCellHeight = new EnumMap<>(BusCell.Direction.class);
if (layoutParam.isAdaptCellHeightToContent()) {
Map<BusCell.Direction, Double> maxInternCellHeight = new EnumMap<>(BusCell.Direction.class);
// Initialize map with intern cells height
// in order to keep intern cells visible if there are no extern cells
getGraph().getCells().stream()
.filter(cell -> cell.getType() == Cell.CellType.INTERN)
.forEach(cell -> maxInternCellHeight.merge(((BusCell) cell).getDirection(), cell.calculateHeight(layoutParam), Math::max));

// when using the adapt cell height to content option, we have to calculate the
// maximum height of all the extern cells in each direction (top and bottom)
getGraph().getCells().stream()
.filter(cell -> cell.getType() == Cell.CellType.EXTERN)
.forEach(cell -> maxCellHeight.compute(((BusCell) cell).getDirection(), (k, v) -> Math.max(v, cell.calculateHeight(layoutParam))));
.forEach(cell -> maxCellHeight.merge(((BusCell) cell).getDirection(), cell.calculateHeight(layoutParam), Math::max));

// if needed, adjusting the maximum calculated cell height to the minimum extern cell height parameter
maxCellHeight.compute(BusCell.Direction.TOP, (k, v) -> Math.max(v, layoutParam.getMinExternCellHeight()) + getFeederSpan(layoutParam));
maxCellHeight.compute(BusCell.Direction.BOTTOM, (k, v) -> Math.max(v, layoutParam.getMinExternCellHeight()) + getFeederSpan(layoutParam));
EnumSet.allOf(BusCell.Direction.class).forEach(d -> maxCellHeight.compute(d, (k, v) -> {
Double vIntern = maxInternCellHeight.get(d);
if (v == null && vIntern == null) {
return 0.;
} else if (v == null) {
return vIntern + layoutParam.getStackHeight();
} else {
return Math.max(v, layoutParam.getMinExternCellHeight()) + layoutParam.getFeederSpan() + layoutParam.getStackHeight();
}
}));
} else {
maxCellHeight.put(BusCell.Direction.TOP, layoutParam.getExternCellHeight());
maxCellHeight.put(BusCell.Direction.BOTTOM, layoutParam.getExternCellHeight());
maxCellHeight.put(BusCell.Direction.TOP, layoutParam.getExternCellHeight() + layoutParam.getStackHeight());
maxCellHeight.put(BusCell.Direction.BOTTOM, layoutParam.getExternCellHeight() + layoutParam.getStackHeight());
}

getGraph().setExternCellHeight(maxCellHeight);
}

public static double getFeederSpan(LayoutParameters layoutParam) {
// The space needed between the feeder and the node connected to it corresponds to the space for feeder arrows
// + half the height of the feeder component + half the height of that node component
return layoutParam.getSpaceForFeederInfos() + layoutParam.getMaxComponentHeight();
getGraph().setMaxCellHeight(maxCellHeight);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import com.fasterxml.jackson.core.JsonGenerator;
import com.powsybl.sld.layout.LayoutParameters;
import com.powsybl.sld.layout.PositionVoltageLevelLayout;
import com.powsybl.sld.model.coordinate.Coord;
import com.powsybl.sld.model.coordinate.Orientation;
import com.powsybl.sld.model.coordinate.Position;
Expand Down Expand Up @@ -185,7 +184,7 @@ private double getRootSpanYCoord(LayoutParameters layoutParam) {
private double getRootBlockSpan(LayoutParameters layoutParam) {
// The Y span of root block does not consider the space needed for the FeederPrimaryBlock (feeder span)
// nor the one needed for the LegPrimaryBlock (layoutParam.getStackHeight())
return getVoltageLevelGraph().getExternCellHeight(((BusCell) cell).getDirection()) - PositionVoltageLevelLayout.getFeederSpan(layoutParam);
return getVoltageLevelGraph().getExternCellHeight(((BusCell) cell).getDirection()) - layoutParam.getStackHeight() - layoutParam.getFeederSpan();
}

private double getRootYCoord(VoltageLevelGraph vlGraph, double spanY, LayoutParameters layoutParam) {
Expand All @@ -201,9 +200,9 @@ private double getRootYCoord(VoltageLevelGraph vlGraph, double spanY, LayoutPara
case BOTTOM:
return vlGraph.getLastBusY(layoutParam) + dyToBus;
case TOP:
return vlGraph.getFirstBusY(layoutParam) - dyToBus;
return vlGraph.getFirstBusY() - dyToBus;
case MIDDLE:
return vlGraph.getFirstBusY(layoutParam) + (getPosition().get(V) - 1) * layoutParam.getVerticalSpaceBus();
return vlGraph.getFirstBusY() + (getPosition().get(V) - 1) * layoutParam.getVerticalSpaceBus();
default:
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void calculateCoord(LayoutParameters layoutParameters) {
double elementaryWidth = layoutParameters.getCellWidth() / 2;
double busPadding = layoutParameters.getBusPadding();
setCoordinates(position.get(H) * elementaryWidth + busPadding,
getVoltageLevelGraph().getFirstBusY(layoutParameters) + position.get(V) * layoutParameters.getVerticalSpaceBus());
getVoltageLevelGraph().getFirstBusY() + position.get(V) * layoutParameters.getVerticalSpaceBus());
setPxWidth(position.getSpan(H) * elementaryWidth - 2 * busPadding);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import com.powsybl.commons.PowsyblException;
import com.powsybl.sld.layout.LayoutParameters;
import com.powsybl.sld.layout.PositionVoltageLevelLayout;

import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -81,7 +80,7 @@ public void coordHorizontalCase(LayoutParameters layoutParam) {

@Override
public void coordVerticalCase(LayoutParameters layoutParam) {
double yFeeder = getConnectedNode().getY() + getOrientation().progressionSign() * PositionVoltageLevelLayout.getFeederSpan(layoutParam);
double yFeeder = getConnectedNode().getY() + getOrientation().progressionSign() * layoutParam.getFeederSpan();
getFeederNode().setCoordinates(getCoord().get(X), yFeeder);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void coordVerticalCase(LayoutParameters layoutParam) {
getLegNode().setX(getCoord().get(X));
if (getCell().getType() == INTERN && ((InternCell) getCell()).checkisShape(UNILEG)) {
getLegNode().setY(getOrientation() == UP
? getVoltageLevelGraph().getFirstBusY(layoutParam) - layoutParam.getInternCellHeight()
? getVoltageLevelGraph().getFirstBusY() - layoutParam.getInternCellHeight()
: getVoltageLevelGraph().getLastBusY(layoutParam) + layoutParam.getInternCellHeight());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ public class VoltageLevelGraph extends AbstractBaseGraph {
// false if substation diagram

// by direction, max calculated height of the extern cells
// If no extern cell found taking into account intern cells too
// (filled and used only when using the adapt cell height to content option)
private Map<BusCell.Direction, Double> externCellHeight = new EnumMap<>(BusCell.Direction.class);
private Map<BusCell.Direction, Double> maxCellHeight = new EnumMap<>(BusCell.Direction.class);

protected VoltageLevelGraph(VoltageLevelInfos voltageLevelInfos, boolean forVoltageLevelDiagram) {
this.voltageLevelInfos = Objects.requireNonNull(voltageLevelInfos);
Expand Down Expand Up @@ -641,11 +642,11 @@ public int getMaxV() {
}

public Double getExternCellHeight(BusCell.Direction direction) {
return !externCellHeight.isEmpty() ? externCellHeight.get(direction) : -1.;
return !maxCellHeight.isEmpty() ? maxCellHeight.get(direction) : -1.;
}

public void setExternCellHeight(Map<BusCell.Direction, Double> externCellHeight) {
this.externCellHeight = externCellHeight;
public void setMaxCellHeight(Map<BusCell.Direction, Double> maxCellHeight) {
this.maxCellHeight = maxCellHeight;
}

public int getMaxHorizontalBusPosition() {
Expand Down Expand Up @@ -681,11 +682,11 @@ public void handleMultiTermsNodeRotation() {
}
}

public double getFirstBusY(LayoutParameters layoutParam) {
return getExternCellHeight(BusCell.Direction.TOP) + layoutParam.getStackHeight();
public double getFirstBusY() {
return getExternCellHeight(BusCell.Direction.TOP);
}

public double getLastBusY(LayoutParameters layoutParam) {
return getFirstBusY(layoutParam) + (getMaxVerticalBusPosition() - 1) * layoutParam.getVerticalSpaceBus();
return getFirstBusY() + (getMaxVerticalBusPosition() - 1) * layoutParam.getVerticalSpaceBus();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.powsybl.iidm.network.*;
import com.powsybl.sld.iidm.extensions.BranchStatus;
import com.powsybl.sld.layout.LayoutParameters;
import com.powsybl.sld.layout.PositionVoltageLevelLayout;
import com.powsybl.sld.library.ComponentLibrary;
import com.powsybl.sld.model.*;

Expand Down Expand Up @@ -189,7 +188,7 @@ private LabelPosition getFeederDecoratorPosition(Node node, String componentType
String positionName = "";
if (node.getCell() != null) {
BusCell.Direction direction = ((BusCell) node.getCell()).getDirection();
yShift = -direction.toOrientation().progressionSign() * PositionVoltageLevelLayout.getFeederSpan(layoutParameters);
yShift = -direction.toOrientation().progressionSign() * layoutParameters.getFeederSpan();
positionName = direction == BusCell.Direction.TOP ? "N" : "S";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ private void drawGrid(String prefixId, Graph graph, Document document, GraphMeta
if (layoutParameters.isShowGrid()) {
for (VoltageLevelGraph vlGraph : graph.getVoltageLevels()) {
if (vlGraph.isPositionNodeBusesCalculated()) {
root.appendChild(drawGrid(prefixId, vlGraph, document, metadata));
drawGrid(prefixId, vlGraph, document, metadata, root);
}
}
}
Expand Down Expand Up @@ -317,7 +317,7 @@ protected void drawSubstation(String prefixId,
/*
* Drawing the grid lines (if required)
*/
protected Element drawGrid(String prefixId, VoltageLevelGraph graph, Document document, GraphMetadata metadata) {
protected void drawGrid(String prefixId, VoltageLevelGraph graph, Document document, GraphMetadata metadata, Element root) {
int maxH = graph.getMaxH();
int maxV = graph.getMaxV();

Expand All @@ -329,21 +329,27 @@ protected Element drawGrid(String prefixId, VoltageLevelGraph graph, Document do

// vertical lines
for (int iCell = 0; iCell < maxH / 2 + 1; iCell++) {
gridRoot.appendChild(drawGridVerticalLine(document, graph, maxV,
graph.getX() + iCell * layoutParameters.getCellWidth()));
drawGridVerticalLine(document, graph, maxV, graph.getX() + iCell * layoutParameters.getCellWidth(), gridRoot);
}

// StackHeight Horizontal lines
gridRoot.appendChild(drawGridHorizontalLine(document, graph, maxH,
graph.getY() + graph.getFirstBusY(layoutParameters) - layoutParameters.getStackHeight()));
gridRoot.appendChild(drawGridHorizontalLine(document, graph, maxH,
graph.getY() + graph.getFirstBusY(layoutParameters) + layoutParameters.getStackHeight() + layoutParameters.getVerticalSpaceBus() * maxV));

// internCellHeight Horizontal lines
gridRoot.appendChild(drawGridHorizontalLine(document, graph, maxH,
graph.getY() + graph.getFirstBusY(layoutParameters) - layoutParameters.getInternCellHeight()));
gridRoot.appendChild(drawGridHorizontalLine(document, graph, maxH,
graph.getY() + graph.getFirstBusY(layoutParameters) + layoutParameters.getInternCellHeight() + layoutParameters.getVerticalSpaceBus() * maxV));
// TOP - Horizontal lines
if (graph.getExternCellHeight(BusCell.Direction.TOP) > 0.) {
// StackHeight
drawGridHorizontalLine(document, graph, maxH, graph.getY() + graph.getFirstBusY() - layoutParameters.getStackHeight(), gridRoot);
// internCellHeight
drawGridHorizontalLine(document, graph, maxH, graph.getY() + graph.getFirstBusY() - layoutParameters.getInternCellHeight(), gridRoot);
// FeederSpan
drawGridHorizontalLine(document, graph, maxH, graph.getY() + layoutParameters.getFeederSpan(), gridRoot);
}
// BOTTOM - Horizontal lines
if (graph.getExternCellHeight(BusCell.Direction.BOTTOM) > 0.) {
// StackHeight
drawGridHorizontalLine(document, graph, maxH, graph.getY() + graph.getFirstBusY() + layoutParameters.getStackHeight() + layoutParameters.getVerticalSpaceBus() * maxV, gridRoot);
// internCellHeight
drawGridHorizontalLine(document, graph, maxH, graph.getY() + graph.getFirstBusY() + layoutParameters.getInternCellHeight() + layoutParameters.getVerticalSpaceBus() * maxV, gridRoot);
// FeederSpan
drawGridHorizontalLine(document, graph, maxH, graph.getY() + graph.getFirstBusY() + graph.getExternCellHeight(BusCell.Direction.BOTTOM) - layoutParameters.getFeederSpan() + layoutParameters.getVerticalSpaceBus() * maxV, gridRoot);
}

metadata.addNodeMetadata(new GraphMetadata.NodeMetadata(gridId,
graph.getVoltageLevelInfos().getId(),
Expand All @@ -356,28 +362,27 @@ protected Element drawGrid(String prefixId, VoltageLevelGraph graph, Document do
null,
Collections.emptyList()));

return gridRoot;
root.appendChild(gridRoot);
}

protected Element drawGridHorizontalLine(Document document, VoltageLevelGraph graph, int maxH, double y) {
return drawGridLine(document,
graph.getX(), y, maxH / 2. * layoutParameters.getCellWidth() + graph.getX(), y);
protected void drawGridHorizontalLine(Document document, VoltageLevelGraph graph, int maxH, double y, Element root) {
drawGridLine(document, graph.getX(), y, maxH / 2. * layoutParameters.getCellWidth() + graph.getX(), y, root);
}

protected Element drawGridVerticalLine(Document document, VoltageLevelGraph graph, int maxV, double x) {
return drawGridLine(document,
x, graph.getY() + graph.getFirstBusY(layoutParameters) - layoutParameters.getStackHeight() - graph.getExternCellHeight(BusCell.Direction.TOP),
x, graph.getY() + graph.getFirstBusY(layoutParameters) + layoutParameters.getStackHeight() + graph.getExternCellHeight(BusCell.Direction.BOTTOM)
+ layoutParameters.getVerticalSpaceBus() * maxV);
protected void drawGridVerticalLine(Document document, VoltageLevelGraph graph, int maxV, double x, Element root) {
drawGridLine(document,
x, graph.getY() + graph.getFirstBusY() - graph.getExternCellHeight(BusCell.Direction.TOP),
x, graph.getY() + graph.getFirstBusY() + graph.getExternCellHeight(BusCell.Direction.BOTTOM)
+ layoutParameters.getVerticalSpaceBus() * maxV, root);
}

protected Element drawGridLine(Document document, double x1, double y1, double x2, double y2) {
protected void drawGridLine(Document document, double x1, double y1, double x2, double y2, Element root) {
Element line = document.createElement("line");
line.setAttribute("x1", Double.toString(x1));
line.setAttribute("x2", Double.toString(x2));
line.setAttribute("y1", Double.toString(y1));
line.setAttribute("y2", Double.toString(y2));
return line;
root.appendChild(line);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.sld.model.FictitiousNode;
import com.powsybl.sld.model.SwitchNode;
import com.powsybl.sld.model.VoltageLevelGraph;
import com.powsybl.sld.svg.BasicStyleProvider;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -50,7 +51,10 @@ public void setUp() {
@Test
public void test() {
VoltageLevelGraph g = rawGraphBuilder.buildVoltageLevelGraph("vl", true);

layoutParameters.setAdaptCellHeightToContent(true);
voltageLevelGraphLayout(g);
assertEquals(toString("/TestCaseComplexCoupling.json"), toJson(g, "/TestCaseComplexCoupling.json"));

assertEquals(toString("/TestCaseComplexCoupling.svg"), toSVG(g, "/TestCaseComplexCoupling.svg", getRawLabelProvider(g), new BasicStyleProvider()));
}
}
Loading