All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
edu.ie3.netpad.map.graphic.GridGraphicImpl Maven / Gradle / Ivy
/*
* © 2020. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.netpad.map.graphic;
import static java.util.stream.Collectors.*;
import com.gluonhq.maps.MapPoint;
import edu.ie3.datamodel.models.UniqueEntity;
import edu.ie3.datamodel.models.input.NodeInput;
import edu.ie3.datamodel.models.input.system.SystemParticipantInput;
import edu.ie3.netpad.map.GridPaintLayer;
import edu.ie3.netpad.map.MapGridElementAttribute;
import edu.ie3.netpad.map.event.NodeGeoPositionUpdateEvent;
import edu.ie3.util.geo.GeoUtils;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Point2D;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Shape;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.impl.CoordinateArraySequence;
/**
* //ToDo: Class Description
*
* @version 0.1
* @since 20.05.20
*/
public abstract class GridGraphicImpl implements GridGraphic {
private static final double DRAG_OPACITY = 0.75;
protected static final Color SLACK_COLOR = MapGridElementAttribute.SLACK.getColor();
protected static final double SLACK_STROKE_WIDTH = 2.0;
private final ObjectProperty nodeGeoPositionUpdateEvent =
new SimpleObjectProperty<>();
protected final GridPaintLayer gridPaintLayer;
protected final Set systemParticipants;
protected final T shape;
public GridGraphicImpl(
GridPaintLayer gridPaintLayer,
T shape,
NodeInput draggableNode,
Set systemParticipants,
List> nodeGeoPositionUpdateEventListener,
String tooltipTxt) {
this.systemParticipants = systemParticipants;
this.shape = shape;
this.gridPaintLayer = gridPaintLayer;
nodeGeoPositionUpdateEventListener.forEach(nodeGeoPositionUpdateEvent::addListener);
draggableNode(draggableNode);
setShapeColor(gridPaintLayer.getLayerColor(), systemParticipants, draggableNode);
installTooltip(shape, tooltipTxt);
}
public GridGraphicImpl(
GridPaintLayer gridPaintLayer,
T shape,
List> nodeGeoPositionUpdateEventListener,
String tooltipTxt) {
this.systemParticipants = Collections.emptySet();
this.shape = shape;
this.gridPaintLayer = gridPaintLayer;
nodeGeoPositionUpdateEventListener.forEach(nodeGeoPositionUpdateEvent::addListener);
installTooltip(shape, tooltipTxt);
}
@Override
public GridPaintLayer getGridPaintLayer() {
return this.gridPaintLayer;
}
@Override
public Set getSystemParticipants() {
return this.systemParticipants;
}
protected void notifyNodeGeoPosListener(
UUID subGridUuid, NodeInput oldNodeInput, Point updatedGeoPosition) {
nodeGeoPositionUpdateEvent.set(
new NodeGeoPositionUpdateEvent(subGridUuid, oldNodeInput, updatedGeoPosition));
}
private void installTooltip(Shape shape, String txt) {
Tooltip.install(shape, new Tooltip(txt));
}
private void setShapeColor(
Color layerColor, Set systemParticipants, NodeInput nodeToBeUpdated) {
Map extends Class extends UniqueEntity>, List> gridEntityColor =
Arrays.stream(MapGridElementAttribute.values())
.collect(groupingBy(MapGridElementAttribute::getClz, toList()));
Set stops = new LinkedHashSet<>();
Set assetColors =
systemParticipants.stream()
.map(
sysPart ->
Optional.ofNullable(gridEntityColor.get(sysPart.getClass()))
.orElseThrow(
() ->
new RuntimeException(
"No map grid attributes defined for element of class '"
+ sysPart.getClass().getSimpleName()
+ "'."))
.get(0)
.getColor())
.collect(Collectors.toSet());
int counter = 0;
Iterator it = assetColors.iterator();
while (it.hasNext()) {
Color c = it.next();
Stop s1 = new Stop((1d / assetColors.size() * counter), c);
Stop s2 = new Stop((1d / assetColors.size() * (counter + 1)), c);
stops.add(s1);
stops.add(s2);
counter++;
}
LinearGradient shapeFill =
new LinearGradient(
0,
0,
1,
0,
true,
CycleMethod.NO_CYCLE,
stops.isEmpty()
? Collections.singletonList(new Stop(0, layerColor))
: new ArrayList<>(stops));
shape.setFill(shapeFill);
// slack node also gets a stroke
if (nodeToBeUpdated.isSlack()) {
shape.setStrokeWidth(SLACK_STROKE_WIDTH);
shape.setStroke(SLACK_COLOR);
}
}
private void draggableNode(NodeInput nodeToBeUpdated) {
AtomicReference orgSceneX = new AtomicReference<>(0d);
AtomicReference orgSceneY = new AtomicReference<>(0d);
AtomicReference translateXClickedDelta = new AtomicReference<>(0d);
shape.addEventHandler(
MouseEvent.MOUSE_PRESSED,
mousePressedEvent -> {
if (mousePressedEvent.getButton().equals(MouseButton.PRIMARY)) {
orgSceneX.set(mousePressedEvent.getSceneX());
orgSceneY.set(mousePressedEvent.getSceneY());
translateXClickedDelta.set(shape.getTranslateX() - orgSceneX.get());
}
});
shape.addEventHandler(
MouseEvent.MOUSE_DRAGGED,
mouseDraggedEvent -> {
if (mouseDraggedEvent.getButton().equals(MouseButton.PRIMARY)) {
shape.setOpacity(DRAG_OPACITY);
shape.toFront();
// correction of drag event offset to keep node directly under the cursor
double deltaX =
mouseDraggedEvent.getSceneX() - orgSceneX.get() + translateXClickedDelta.get();
double deltaY = mouseDraggedEvent.getSceneY() - orgSceneY.get() - 55;
shape.setTranslateX(mouseDraggedEvent.getSceneX() + deltaX);
shape.setTranslateY(mouseDraggedEvent.getSceneY() + deltaY);
orgSceneX.set(mouseDraggedEvent.getSceneX());
orgSceneY.set(mouseDraggedEvent.getSceneY());
mouseDraggedEvent.consume();
}
});
shape.addEventHandler(
MouseEvent.MOUSE_RELEASED,
mouseReleasedEvent -> {
if (mouseReleasedEvent.getButton().equals(MouseButton.PRIMARY)) {
// refresh corresponding map point and inform listener
MapPoint updatedPoint =
gridPaintLayer.getMapPosition(shape.getTranslateX(), shape.getTranslateY());
// we don't want this node to stay on the new place, but wait for the grid update event
// --> reset to starting position
setNodeToBeUpdatedCoords(nodeToBeUpdated);
// reset opacity after dragging
shape.setOpacity(1.0);
notifyNodeGeoPosListener(
gridPaintLayer.getSubGridUuid(), nodeToBeUpdated, updateNodeGeoPos(updatedPoint));
mouseReleasedEvent.consume();
}
});
}
protected void setNodeToBeUpdatedCoords(NodeInput nodeToBeUpdated) {
Point2D mapPoint =
gridPaintLayer.getGridLayerPoint(
nodeToBeUpdated.getGeoPosition().getY(), nodeToBeUpdated.getGeoPosition().getX());
shape.setTranslateX(mapPoint.getX());
shape.setTranslateY(mapPoint.getY());
}
private Point updateNodeGeoPos(MapPoint updatedPoint) {
Coordinate[] coord =
new Coordinate[] {new Coordinate(updatedPoint.getLongitude(), updatedPoint.getLatitude())};
CoordinateArraySequence coordSeq = new CoordinateArraySequence(coord);
return new Point(coordSeq, GeoUtils.DEFAULT_GEOMETRY_FACTORY);
}
}