package org.wikibrain.spatial.distance;
import com.vividsolutions.jts.geom.*;
import org.geotools.referencing.GeodeticCalculator;
import org.junit.Ignore;
import org.junit.Test;
import org.wikibrain.core.dao.DaoException;
import org.wikibrain.spatial.constants.Precision;
import org.wikibrain.spatial.dao.SpatialDataDao;
import org.wikibrain.spatial.loader.SpatialDataLoader;
import org.wikibrain.sr.utils.Leaderboard;
import org.wikibrain.utils.Scoreboard;
import java.util.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* @author Shilad Sen
*/
public class TestGeodeticDistanceMetric {
private Random random = new Random();
private GeometryFactory factory = new GeometryFactory(new PrecisionModel(),8307);
@Ignore
@Test
public void testKnnManyTimes() throws DaoException {
for (int i= 0; i < 100; i++) {
testKnn();
}
}
@Test
public void testKnn() throws DaoException {
int numNeighbors = 100;
Point query = makePoint();
Scoreboard<Point> actual = new Scoreboard<Point>(numNeighbors, Scoreboard.Order.INCREASING);
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(query.getX(), query.getY());
Map<Integer, Geometry> points = new HashMap<Integer, Geometry>();
int diverged = 0;
for (int i = 0; i < 100000; i++) {
Point p = makePoint();
points.put(i * 3, p);
calc.setDestinationGeographicPoint(p.getX(), p.getY());
try {
actual.add(p, calc.getOrthodromicDistance());
} catch (ArithmeticException e) {
diverged++;
}
}
System.err.println("number of diverged points: " + diverged);
SpatialDataDao dao = mock(SpatialDataDao.class);
when(dao.getAllGeometriesInLayer("wikidata", Precision.LatLonPrecision.HIGH))
.thenReturn(points);
SphericalDistanceMetric spherical = new SphericalDistanceMetric(dao);
spherical.enableCache(true);
GeodeticDistanceMetric metric = new GeodeticDistanceMetric(dao, spherical);
metric.enableCache(true);
System.out.println("Closest points to " + query + " are: ");
long before = System.currentTimeMillis();
List<SpatialDistanceMetric.Neighbor> neighbors = metric.getNeighbors(query, numNeighbors);
long after = System.currentTimeMillis();
System.err.println("elapsed millis is " + (after - before));
for (int i = 0; i < numNeighbors; i++) {
SpatialDistanceMetric.Neighbor n = neighbors.get(i);
Point p1 = actual.getElement(i);
Geometry p2 = (Point)points.get(n.conceptId);
assertEquals(n.distance, actual.getScore(i), n.distance * 0.005); // maximum error due to ellipsoid is 0.5%
// System.out.println("\tgot" + p2 + " with distance " + n.distance + " expected " + p1 + " with distance " + actual.getScore(i));
}
}
@Test
public void testMatrix() throws DaoException {
SpatialDataDao dao = mock(SpatialDataDao.class);
when(dao.getAllGeometriesInLayer("wikidata", Precision.LatLonPrecision.HIGH))
.thenReturn(new HashMap<Integer, Geometry>());
SphericalDistanceMetric spherical = new SphericalDistanceMetric(dao);
spherical.enableCache(true);
GeodeticDistanceMetric metric = new GeodeticDistanceMetric(dao, spherical);
List<Geometry> cols = new ArrayList<Geometry>();
List<Geometry> rows = new ArrayList<Geometry>();
for (int i = 0; i < 10; i++) {
cols.add(makePoint());
}
for (int i = 0; i < 5; i++) {
rows.add(makePoint());
}
float [][] distance = metric.distance(rows, cols);
for (int i = 0; i < cols.size(); i++) {
for (int j = 0; j < rows.size(); j++) {
// System.err.println("i " +i + ", j " + j);
assertEquals(metric.distance(rows.get(j), cols.get(i)), distance[j][i], 1.5);
}
}
}
private Point makePoint() {
double lat = 90 - random.nextDouble() * 180;
double lon = 180 - random.nextDouble() * 360;
return factory.createPoint(new Coordinate(lon, lat));
}
}