GreenIndexGraphStorageBuilder.java

  1. /*  This file is part of Openrouteservice.
  2.  *
  3.  *  Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the
  4.  *  GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1
  5.  *  of the License, or (at your option) any later version.

  6.  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  7.  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8.  *  See the GNU Lesser General Public License for more details.

  9.  *  You should have received a copy of the GNU Lesser General Public License along with this library;
  10.  *  if not, see <https://www.gnu.org/licenses/>.
  11.  */
  12. package org.heigit.ors.routing.graphhopper.extensions.storages.builders;

  13. import com.graphhopper.GraphHopper;
  14. import com.graphhopper.reader.ReaderWay;
  15. import com.graphhopper.storage.GraphExtension;
  16. import com.graphhopper.util.EdgeIteratorState;
  17. import com.graphhopper.util.Helper;
  18. import org.apache.log4j.Logger;
  19. import org.heigit.ors.routing.graphhopper.extensions.storages.GreenIndexGraphStorage;

  20. import java.io.BufferedReader;
  21. import java.io.FileReader;
  22. import java.io.IOException;
  23. import java.util.Collections;
  24. import java.util.HashMap;
  25. import java.util.Map;

  26. /**
  27.  * Created by lliu on 13/03/2017.
  28.  */
  29. public class GreenIndexGraphStorageBuilder extends AbstractGraphStorageBuilder {
  30.     private static final Logger LOGGER = Logger.getLogger(GreenIndexGraphStorageBuilder.class.getName());

  31.     private GreenIndexGraphStorage storage;
  32.     private final Map<Long, Double> greenIndices = new HashMap<>();
  33.     private static final int TOTAL_LEVEL = 64;
  34.     private static final int DEFAULT_LEVEL = TOTAL_LEVEL - 1;
  35.     private final Map<Byte, SlotRange> slots = new HashMap<>(TOTAL_LEVEL);

  36.     @Override
  37.     public GraphExtension init(GraphHopper graphhopper) throws Exception {
  38.         if (storage != null)
  39.             throw new Exception("GraphStorageBuilder has been already initialized.");

  40.         // TODO Refactoring Check if the _greenIndexFile exists
  41.         String csvFile = parameters.get("filepath");
  42.         readGreenIndicesFromCSV(csvFile);
  43.         prepareGreenIndexSlots();
  44.         storage = new GreenIndexGraphStorage();

  45.         return storage;
  46.     }

  47.     private void prepareGreenIndexSlots() {
  48.         double max = Collections.max(greenIndices.values());
  49.         double min = Collections.min(greenIndices.values());
  50.         double step = (max - min) / TOTAL_LEVEL;
  51.         // Divide the range of raw green index values into TOTAL_LEVEL,
  52.         // then map the raw value to [0..TOTAL_LEVEL - 1]
  53.         for (byte i = 0; i < TOTAL_LEVEL; i++) {
  54.             slots.put(i, new SlotRange(min + i * step, min + (i + 1) * step));
  55.         }
  56.     }

  57.     private void readGreenIndicesFromCSV(String csvFile) throws IOException {
  58.         try (BufferedReader csvBuffer = new BufferedReader(new FileReader(csvFile))) {
  59.             String row;
  60.             // Jump the header line
  61.             row = csvBuffer.readLine();
  62.             char separator = row.contains(";") ? ';' : ',';
  63.             String[] rowValues = new String[2];

  64.             while ((row = csvBuffer.readLine()) != null) {
  65.                 if (!parseCSVrow(row, separator, rowValues))
  66.                     continue;

  67.                 greenIndices.put(Long.parseLong(rowValues[0]), Double.parseDouble(rowValues[1]));
  68.             }
  69.         } catch (IOException openFileEx) {
  70.             LOGGER.error(openFileEx.getStackTrace());
  71.             throw openFileEx;
  72.         }
  73.     }

  74.     private boolean parseCSVrow(String row, char separator, String[] rowValues) {
  75.         if (Helper.isEmpty(row))
  76.             return false;

  77.         int pos = row.indexOf(separator);
  78.         if (pos > 0) {
  79.             rowValues[0] = row.substring(0, pos).trim();
  80.             rowValues[1] = row.substring(pos + 1).trim();
  81.             // read, check and push "osm_id" and "ungreen_factor" values
  82.             return !Helper.isEmpty(rowValues[0]) && !Helper.isEmpty(rowValues[1]);
  83.         }
  84.         return false;
  85.     }

  86.     @Override
  87.     public void processWay(ReaderWay way) {
  88.         // do nothing
  89.     }

  90.     @Override
  91.     public void processEdge(ReaderWay way, EdgeIteratorState edge) {
  92.         storage.setEdgeValue(edge.getEdge(), calcGreenIndex(way.getId()));
  93.     }

  94.     private static class SlotRange {
  95.         double left = 0.0;
  96.         double right = 0.0;

  97.         SlotRange(double l, double r) {
  98.             this.left = l;
  99.             this.right = r;
  100.         }

  101.         boolean within(double val) {
  102.             // check if the @val falls in [left, right] range
  103.             return (val >= left) && (val <= right);
  104.         }
  105.     }

  106.     private byte calcGreenIndex(long id) {
  107.         Double gi = greenIndices.get(id);

  108.         // No such @id key in the _greenIndices, or the value of it is null
  109.         // We set its green level to TOTAL_LEVEL/2 indicating the middle value for such cases
  110.         // TODO Refactoring this DEFAULT_LEVEL should be put in the ors-config.json file and
  111.         // injected back in the code
  112.         if (gi == null)
  113.             return (byte) (DEFAULT_LEVEL);

  114.         for (Map.Entry<Byte, SlotRange> s : slots.entrySet()) {
  115.             if (s.getValue().within(gi))
  116.                 return s.getKey();
  117.         }
  118.         return (byte) (DEFAULT_LEVEL);
  119.     }

  120.     @Override
  121.     public String getName() {
  122.         return "GreenIndex";
  123.     }
  124. }