package org.wikibrain.spatial.cookbook.tflevaluate; import com.vividsolutions.jts.geom.Geometry; import org.geotools.referencing.GeodeticCalculator; import org.wikibrain.conf.ConfigurationException; import org.wikibrain.conf.Configurator; import org.wikibrain.core.cmd.Env; import org.wikibrain.core.cmd.EnvBuilder; import org.wikibrain.core.dao.DaoException; import org.wikibrain.spatial.dao.SpatialNeighborDao; import java.util.*; /** * Created by toby on 5/15/14. */ public class DistanceMetrics { Env env; Configurator c; SpatialNeighborDao snDao; public DistanceMetrics() throws ConfigurationException{ env = new EnvBuilder().build(); c = env.getConfigurator(); snDao = c.get(SpatialNeighborDao.class); } public DistanceMetrics(Env env, Configurator c, SpatialNeighborDao snDao){ this.env = env; this.c = c; this.snDao = snDao; } public double getDistance(Geometry a, Geometry b){ GeodeticCalculator geoCalc = new GeodeticCalculator(); geoCalc.setStartingGeographicPoint(a.getCoordinate().x, a.getCoordinate().y); geoCalc.setDestinationGeographicPoint(b.getCoordinate().x, b.getCoordinate().y); return geoCalc.getOrthodromicDistance() / 1000; } public int getTopologicalDistance(Geometry a, Integer itemIdA, Geometry b, Integer itemIdB, int k, String layerName, String refSysName) throws DaoException{ int counter = 0; Map<Integer, Geometry> currentLevel = new HashMap<Integer, Geometry>(); Set<Integer> discoveredPoint = new HashSet<Integer>(); currentLevel.put(itemIdA, a); discoveredPoint.add(itemIdA); while(!currentLevel.isEmpty()){ counter ++; Map<Integer, Geometry> neighbors = new HashMap<Integer, Geometry>(); for(Integer i : currentLevel.keySet()){ Map<Integer, Geometry> singleNeighbors = snDao.getKNNeighbors(a, k, layerName,refSysName, discoveredPoint); if (singleNeighbors.keySet().contains(itemIdB)) return counter; for(Integer m : singleNeighbors.keySet()){ if(discoveredPoint.contains(m)) continue; discoveredPoint.add(m); neighbors.put(m, singleNeighbors.get(m)); } } currentLevel = neighbors; } return -1; } public Map<Integer,Integer> getGraphDistance(Integer itemIdA, Map<Integer,Geometry> compareTo, int k, int maxTopoDistance, float[][] distanceMatrix) throws DaoException{ Geometry a = compareTo.get(itemIdA); // topologies in current level Map<Integer, Geometry> currentLevel = new HashMap<Integer, Geometry>(); // topologies found so far Set<Integer> discoveredPoint = new HashSet<Integer>(); // result map Map<Integer,Integer> idToDistance = new HashMap<Integer, Integer>(); currentLevel.put(itemIdA, a); discoveredPoint.add(itemIdA); idToDistance.put(itemIdA, 0); // ids in order List<Integer> order = new ArrayList<Integer>(); order.addAll(compareTo.keySet()); for (int curTopoDistance=1; curTopoDistance<=maxTopoDistance; curTopoDistance++){ // if no points in current level, leave loop if (currentLevel.isEmpty()){ System.out.println("Too high: "+curTopoDistance); break; } // newly discovered neighbors Map<Integer, Geometry> neighbors = new HashMap<Integer, Geometry>(); // find all current level geometries' neighbors for(Integer i : currentLevel.keySet()){ // Map<Integer, Geometry> singleNeighbors = snDao.getKNNeighbors(compareTo.get(i), k, layerName,refSysName, discoveredPoint); // add new neighbors to discoveredPoint and neighbors Map<Integer, Geometry> singleNeighbors = getKNNeighbors(k, compareTo, distanceMatrix[order.indexOf(i)]); for(Integer m : singleNeighbors.keySet()){ if(!discoveredPoint.contains(m)) { discoveredPoint.add(m); neighbors.put(m, singleNeighbors.get(m)); } } } // System.out.println(curTopoDistance+" "+neighbors.keySet().size()); // new currentLevel currentLevel = neighbors; // loop over it to find geometries with this topo distance for (Integer i: currentLevel.keySet()){ if (compareTo.keySet().contains(i)){ idToDistance.put(i,curTopoDistance); } } } System.out.println("id = "+itemIdA); System.out.println("total "+idToDistance.size()); return idToDistance; } public Set<Integer> getGraphDistance(Map<Integer,Geometry> compareTo, int k, int maxTopoDistance, float[][] significantDistanceMatrix, float[] cityDistanceMatrix) throws DaoException{ // topologies in current level Map<Integer,Geometry> currentLevel = getKNNeighbors(k,compareTo,cityDistanceMatrix); // topologies found so far Set<Integer> discoveredPoints = new HashSet<Integer>(); // ids in order List<Integer> order = new ArrayList<Integer>(); order.addAll(compareTo.keySet()); // loop over possible graph distances for (int curTopoDistance=2; curTopoDistance<=maxTopoDistance; curTopoDistance++){ // if no points in current level, leave loop if (currentLevel.isEmpty()){ System.out.println("Too high: "+curTopoDistance); break; } // newly discovered neighbors Map<Integer, Geometry> neighbors = new HashMap<Integer, Geometry>(); // find all current level geometries' neighbors for(Integer i : currentLevel.keySet()){ // add new neighbors to discoveredPoint and neighbors Map<Integer, Geometry> singleNeighbors = getKNNeighbors( k, compareTo, significantDistanceMatrix[order.indexOf(i)]); for(Integer m : singleNeighbors.keySet()){ if(!discoveredPoints.contains(m)) { discoveredPoints.add(m); neighbors.put(m, singleNeighbors.get(m)); } } } // new currentLevel currentLevel = neighbors; } return discoveredPoints; } public Map<Integer, Geometry> getKNNeighbors( int k, Map<Integer, Geometry> geometries, final float[] distanceMatrix ) throws DaoException { final List<Integer> order = new ArrayList<Integer>(); order.addAll(geometries.keySet()); Map<Integer, Geometry> result = new HashMap<Integer, Geometry>(); Collections.sort(order, new Comparator<Integer>() { @Override public int compare(Integer integer, Integer integer2) { double dist1 = distanceMatrix[order.indexOf(integer)]; double dist2 = distanceMatrix[order.indexOf(integer2)]; return Double.compare(dist1, dist2); } }); for (int i =1; i<=k; i++){ result.put(order.get(i),geometries.get(order.get(i))); } return result; } }