Projector.java

  1. package org.heigit.ors.fastisochrones.partitioning;

  2. import com.carrotsearch.hppc.IntArrayList;
  3. import com.carrotsearch.hppc.IntHashSet;
  4. import com.graphhopper.storage.GraphHopperStorage;
  5. import org.heigit.ors.fastisochrones.Contour;

  6. import java.util.EnumMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.stream.IntStream;

  10. import static org.heigit.ors.fastisochrones.partitioning.FastIsochroneParameters.getSplitValue;
  11. import static org.heigit.ors.fastisochrones.partitioning.Projector.Projection.*;

  12. public class Projector {
  13.     protected static Map<Projection, Projection> correspondingProjMap;
  14.     private GraphHopperStorage ghStorage;
  15.     private static final double TAN_67_5 = 2.414213;
  16.     private static final double TAN_45 = 1;
  17.     private static final double TAN_22_5 = 0.414213;


  18.     public Projector() {
  19.         prepareProjectionMaps();
  20.     }

  21.     private static void prepareProjectionMaps() {
  22.         correspondingProjMap = new EnumMap<>(Projection.class);
  23.         correspondingProjMap.put(LINE_P90, LINE_M00);
  24.         correspondingProjMap.put(LINE_P675, LINE_M225);
  25.         correspondingProjMap.put(LINE_P45, LINE_M45);
  26.         correspondingProjMap.put(LINE_P225, LINE_M675);
  27.         correspondingProjMap.put(LINE_M00, LINE_P90);
  28.         correspondingProjMap.put(LINE_M225, LINE_P675);
  29.         correspondingProjMap.put(LINE_M45, LINE_P45);
  30.         correspondingProjMap.put(LINE_M675, LINE_P225);
  31.     }

  32.     protected Map<Projection, IntArrayList> calculateProjections() {
  33.         //>> Loop through linear combinations and project each Node
  34.         EnumMap<Projection, IntArrayList> nodeListProjMap = new EnumMap<>(Projection.class);
  35.         Integer[] ids = IntStream.rangeClosed(0, ghStorage.getNodes() - 1).boxed().toArray(Integer[]::new);

  36.         Double[] values = new Double[ids.length];
  37.         Sort sort = new Sort();
  38.         for (Projection proj : Projection.values()) {
  39.             //>> sort projected Nodes
  40.             for (int i = 0; i < ids.length; i++) {
  41.                 values[i] = proj.sortValue(ghStorage.getNodeAccess().getLat(ids[i]), ghStorage.getNodeAccess().getLon(ids[i]));
  42.             }
  43.             nodeListProjMap.put(proj, sort.sortByValueReturnList(ids, values));
  44.         }
  45.         //Check if there are at least two differing projections. If no lat lon data is set, all projections are the same.
  46.         boolean valid = false;
  47.         for (Projection proj : Projection.values()) {
  48.             if (!nodeListProjMap.get(proj).equals(nodeListProjMap.get(LINE_M00)))
  49.                 valid = true;
  50.         }
  51.         if (!valid)
  52.             throw new IllegalStateException("All projections of the graph are the same. Maybe NodeAccess is faulty or not initialized?");
  53.         return nodeListProjMap;
  54.     }

  55.     protected BiPartitionProjection partitionProjections(Map<Projection, IntArrayList> originalProjections, BiPartition biPartition) {
  56.         IntHashSet part0 = biPartition.getPartition(0);
  57.         EnumMap<Projection, IntArrayList> projections0 = new EnumMap<>(Projection.class);
  58.         EnumMap<Projection, IntArrayList> projections1 = new EnumMap<>(Projection.class);
  59.         int origNodeCount = originalProjections.get(Projection.values()[0]).size();
  60.         //Add initial lists
  61.         for (Projection proj : Projection.values()) {
  62.             projections0.put(proj, new IntArrayList(origNodeCount / 3));
  63.             projections1.put(proj, new IntArrayList(origNodeCount / 3));
  64.         }

  65.         //Go through the original projections and separate each into two projections for the subsets, maintaining order
  66.         for (int i = 0; i < origNodeCount; i++) {
  67.             for (Map.Entry<Projection, IntArrayList> proj : originalProjections.entrySet()) {
  68.                 int node = proj.getValue().get(i);
  69.                 if (part0.contains(node))
  70.                     projections0.get(proj.getKey()).add(node);
  71.                 else
  72.                     projections1.get(proj.getKey()).add(node);
  73.             }
  74.         }

  75.         return new BiPartitionProjection(projections0, projections1);
  76.     }

  77.     protected List<Projection> calculateProjectionOrder(Map<Projection, IntArrayList> projections) {
  78.         List<Projection> order;
  79.         EnumMap<Projection, Double> squareRangeProjMap = new EnumMap<>(Projection.class);
  80.         EnumMap<Projection, Double> orthogonalDiffProjMap = new EnumMap<>(Projection.class);
  81.         //>> calculate Projection-Distances
  82.         for (Map.Entry<Projection, IntArrayList> proj : projections.entrySet()) {
  83.             int idx = (int) (proj.getValue().size() * getSplitValue());
  84.             squareRangeProjMap.put(proj.getKey(), projIndividualValue(projections, proj.getKey(), idx));
  85.         }

  86.         //>> combine inverse Projection-Distances
  87.         for (Projection proj : projections.keySet()) {
  88.             orthogonalDiffProjMap.put(proj, projCombinedValue(squareRangeProjMap, proj));
  89.         }

  90.         //>> order Projections by Projection-Value
  91.         Sort sort = new Sort();
  92.         order = sort.sortByValueReturnList(orthogonalDiffProjMap, false);
  93.         return order;
  94.     }

  95.     private double projIndividualValue(Map<Projection, IntArrayList> projMap, Projection proj, int idx) {
  96.         IntArrayList tmpNodeList = projMap.get(proj);
  97.         double toLat = ghStorage.getNodeAccess().getLat(tmpNodeList.get(idx));
  98.         double toLon = ghStorage.getNodeAccess().getLon(tmpNodeList.get(idx));
  99.         double fromLat = ghStorage.getNodeAccess().getLat(tmpNodeList.get(tmpNodeList.size() - idx - 1));
  100.         double fromLon = ghStorage.getNodeAccess().getLon(tmpNodeList.get(tmpNodeList.size() - idx - 1));

  101.         return Contour.distance(fromLat, toLat, fromLon, toLon);
  102.     }

  103.     private double projCombinedValue(Map<Projection, Double> squareRangeProjMap, Projection proj) {
  104.         return squareRangeProjMap.get(proj) * squareRangeProjMap.get(proj) / squareRangeProjMap.get(correspondingProjMap.get(proj));
  105.     }

  106.     public void setGHStorage(GraphHopperStorage ghStorage) {
  107.         this.ghStorage = ghStorage;
  108.     }

  109.     public enum Projection {
  110.         LINE_P90 {
  111.             public double sortValue(double lat, double lon) {
  112.                 return lat;
  113.             }
  114.         },
  115.         LINE_P675 {
  116.             public double sortValue(double lat, double lon) {
  117.                 return lat + TAN_67_5 * lon;
  118.             }
  119.         },
  120.         LINE_P45 {
  121.             public double sortValue(double lat, double lon) {
  122.                 return lat + TAN_45 * lon;
  123.             }
  124.         },
  125.         LINE_P225 {
  126.             public double sortValue(double lat, double lon) {
  127.                 return lat + TAN_22_5 * lon;
  128.             }
  129.         },
  130.         LINE_M00 {
  131.             public double sortValue(double lat, double lon) {
  132.                 return lon;
  133.             }
  134.         },
  135.         LINE_M225 {
  136.             public double sortValue(double lat, double lon) {
  137.                 return lat - TAN_22_5 * lon;
  138.             }
  139.         },
  140.         LINE_M45 {
  141.             public double sortValue(double lat, double lon) {
  142.                 return lat - TAN_45 * lon;
  143.             }
  144.         },
  145.         LINE_M675 {
  146.             public double sortValue(double lat, double lon) {
  147.                 return lat - TAN_67_5 * lon;
  148.             }
  149.         };

  150.         abstract double sortValue(double lat, double lon);
  151.     }
  152. }