All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.ie3.netpad.map.MapController 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;

import com.gluonhq.maps.MapPoint;
import com.gluonhq.maps.MapView;
import edu.ie3.netpad.grid.event.GridEvent;
import edu.ie3.netpad.grid.event.GridEventListener;
import edu.ie3.netpad.grid.event.ReplaceGridEvent;
import edu.ie3.netpad.grid.event.UpdateGridEvent;
import edu.ie3.netpad.grid.info.GridInfoEvent;
import edu.ie3.netpad.map.event.MapEvent;
import edu.ie3.netpad.util.ListenerUtil;
import edu.ie3.netpad.util.RandomSingleton;
import java.util.*;
import java.util.stream.Collectors;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * //ToDo: Class Description
 *
 * @version 0.1
 * @since 19.05.20
 */
public class MapController implements GridEventListener {

  private static final Logger logger = LoggerFactory.getLogger(MapController.class);

  // Default zoom value and location
  private static final int ZOOM_DEFAULT = 6;
  private static final MapPoint FUERWEILER = new MapPoint(49.3765, 6.59384);

  private final ObjectProperty papUpdateEventProperty = new SimpleObjectProperty<>();
  private final Map subGridGraphicLayer = new HashMap<>();

  private final ChangeListener gridEventListener =
      ListenerUtil.createGridEventListener(this);

  @FXML private MapView map;

  @Override
  public ChangeListener gridEventListener() {
    return gridEventListener;
  }

  @FXML
  public void initialize() {

    map.setCenter(FUERWEILER);
    map.setZoom(ZOOM_DEFAULT);

    // add information caption to the mapAnchorPane
    map.addLayer(new CaptionLayer());
  }

  @Override
  public void handleGridEvent(GridEvent gridEvent) {
    if (gridEvent instanceof UpdateGridEvent) {
      handleUpdateGridEvent((UpdateGridEvent) gridEvent);
    } else if (gridEvent instanceof ReplaceGridEvent) {
      handleReplaceGridEvent((ReplaceGridEvent) gridEvent);
    } else {
      throw new RuntimeException(
          "The provided GridEvent "
              + gridEvent.getClass().getSimpleName()
              + " is not supported by the MapController!");
    }
  }

  private void handleReplaceGridEvent(ReplaceGridEvent gridEvent) {

    // clear base map
    subGridGraphicLayer.values().forEach(map::removeLayer);

    // clear subGridGraphicLayer map
    subGridGraphicLayer.clear();

    // todo preserve grid layer order

    // create layer for each subGrid and add them to the subGridGraphicLayer map
    gridEvent
        .getSubGrids()
        .forEach(
            (subGridUuid, subGrid) -> {
              Set existingColors =
                  subGridGraphicLayer.values().stream()
                      .map(GridPaintLayer::getLayerColor)
                      .collect(Collectors.toSet());
              Color uniqueColor = getUniqueLayerColor(existingColors);

              GridPaintLayer gridPaintLayer =
                  new GridPaintLayer(subGridUuid, layerUpdateListener(), uniqueColor);

              // needs to be called before the layer can draw its grid because this makes the
              // baseMap accessible to the layer
              map.addLayer(gridPaintLayer);

              // add the grid to the layer
              gridPaintLayer.initGridGraphics(subGrid);

              subGridGraphicLayer.put(gridPaintLayer.getSubGridUuid(), gridPaintLayer);
            });

    // adapt map center and zoom for better user experience
    subGridGraphicLayer.keySet().stream()
        .findAny()
        .flatMap(
            randomUuid ->
                gridEvent.getSubGrids().get(randomUuid).getRawGrid().getNodes().stream().findAny())
        .ifPresent(
            randomNodeInGrid ->
                map.setCenter(
                    new MapPoint(
                        randomNodeInGrid.getGeoPosition().getY(),
                        randomNodeInGrid.getGeoPosition().getX())));
    map.setZoom(11);
  }

  private Color getUniqueLayerColor(Set existingColors) {
    Color uniqueLayerColor = existingColors.stream().findAny().orElseGet(this::randomColor);
    List reservedColors =
        Arrays.stream(MapGridElementAttribute.values())
            .map(MapGridElementAttribute::getColor)
            .collect(Collectors.toList());
    if (!existingColors.isEmpty()) {
      // uniqueness by checking if the color exist and if the color is not black, as black is
      // reserved for slack nodes
      while (existingColors.contains(uniqueLayerColor)
          || reservedColors.contains(uniqueLayerColor)) {
        uniqueLayerColor = randomColor();
      }
    }
    return uniqueLayerColor;
  }

  private void handleUpdateGridEvent(UpdateGridEvent updateGridEvent) {

    subGridGraphicLayer.get(updateGridEvent.getSubGridUuid()).updateGraphicEntity(updateGridEvent);

    logger.debug("Received GridEvent: {}", updateGridEvent);
  }

  private ChangeListener layerUpdateListener() {
    return (observable, oldValue, newValue) -> notifyListener(newValue);
  }

  private void notifyListener(MapEvent newValue) {
    papUpdateEventProperty.set(newValue);
  }

  public ObjectProperty mapUpdateEvents() {
    return papUpdateEventProperty;
  }

  protected Color randomColor() {

    double r = ((RandomSingleton.nextFloat() * RandomSingleton.nextDouble()) / 2f + 0.25f);
    double g = ((RandomSingleton.nextFloat() * RandomSingleton.nextDouble()) / 2f + 0.25f);
    double b = RandomSingleton.nextDouble() / 2d + 0.25d;

    return new Color(r, g, b, 1);
  }

  public ChangeListener gridInfoEventListener() {
    return (observable, oldValue, newValue) -> handleGridInfoEvent(newValue);
  }

  private void handleGridInfoEvent(GridInfoEvent gridInfoEvent) {

    GridPaintLayer layer = subGridGraphicLayer.get(gridInfoEvent.getSubGridUuid());
    if (gridInfoEvent.isSelected()) {
      map.addLayer(layer);
    } else {
      map.removeLayer(layer);
    }

    // refresh view
    layer.layoutLayer();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy