/**
* Copyright (c) 2013 Oculus Info Inc.
* http://www.oculusinfo.com/
*
* Released under the MIT License.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package spimedb.cluster.distance;
import org.junit.Test;
import spimedb.cluster.feature.spatial.GeoSpatialFeature;
import spimedb.cluster.feature.spatial.distance.SphericalCosineDistance;
import java.util.Collections;
import static org.junit.Assert.assertTrue;
public class TestSphericalCosineDistance {
final double epsilon = 0.00001;
private boolean isEqual(double d1, double d2) {
return (Math.abs( d1 - d2 ) < epsilon );
}
@Test
public void testIdenticalPoints() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
double lat = 43.650514, lon = -79.363672;
t1.setValue(lat, lon);
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(lat, lon);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
assertTrue(isEqual(distance, 0));
distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
System.out.println(distance);
assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric1() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
double lat = 43.650514, lon = -79.363672;
t1.setValue(lat, lon);
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(lat, lon);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceSameCity() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Oculus -79.3636716??W, 43.6505143N
t1.setValue(43.6505143, -79.3636716);
// Etobicoke -79.5440954??W, 43.6389057??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(43.6389057, -79.5440954);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
assertTrue(isEqual(distance, 7.281985816507403E-4));
distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
assertTrue(isEqual(distance, 7.281985816507403E-4));
}
@Test
public void testSymmetric2() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Oculus -79.3636716??W, 43.6505143N
t1.setValue(43.6505143, -79.3636716);
// Etobicoke -79.5440954??W, 43.6389057??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(43.6389057, -79.5440954);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceSameProvince() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Toronto -79.3831843??W, 43.6532260??N
t1.setValue(43.6532260, -79.3831843);
// Waterloo -80.5204096??W, 43.4642578??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(43.4642578, -80.5204096);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric3() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Toronto -79.3831843??W, 43.6532260??N
t1.setValue(43.6532260, -79.3831843);
// Waterloo -80.5204096??W, 43.4642578??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(43.4642578, -80.5204096);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceDifferentProvinces() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Ontario -85.3232139??W, 51.2537750??N
t1.setValue(51.2537750, -85.3232139);
// BC -127.6476206??W, 53.7266683??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(53.7266683, -127.6476206);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric4() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Ontario -85.3232139??W, 51.2537750??N
t1.setValue(51.2537750, -85.3232139);
// BC -127.6476206??W, 53.7266683??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(53.7266683, -127.6476206);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceDifferentContintent() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Canada -106.3467710??W, 56.1303660??N
t1.setValue(56.1303660, -106.3467710);
// Africa 34.5085230??E, -8.7831950??S
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-8.7831950, 34.5085230);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric5() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Canada -106.3467710??W, 56.1303660??N
t1.setValue(56.1303660, -106.3467710);
// Africa 34.5085230??E, -8.7831950??S
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-8.7831950, 34.5085230);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceNearPoles() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Antarctica -135.0000000??W, -82.8627519??S
t1.setValue(-82.8627519, -135.0000000);
// Arctic 45??E, 82.8627519??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(82.8627519, 45);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric6() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// Antarctica -135.0000000??W, -82.8627519??S
t1.setValue(-82.8627519, -135.0000000);
// Arctic 45??E, 82.8627519??N
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(82.8627519, 45);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@Test
public void testDistanceOppposite() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// -106.3467710??W, 56.1303660??N
t1.setValue(56.1303660, -106.3467710);
// 73.653229??E, -56.130366??S
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-56.130366, 73.653229);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
System.out.println(distance);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric7() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// -106.3467710??W, 56.1303660??N
t1.setValue(56.1303660, -106.3467710);
// 73.653229??E, -56.130366??S
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-56.130366, 73.653229);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
@SuppressWarnings("unused")
@Test
public void testTiming() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// -106.3467710??W, 56.1303660??N
t1.setValue(56.1303660, -106.3467710);
// 73.653229??E, -56.130366??S
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-56.130366, 73.653229);
SphericalCosineDistance d = new SphericalCosineDistance(1);
// EuclideanDistance d = new EuclideanDistance(1);
long start = System.currentTimeMillis();
double distance = 0;
for (int i=0; i < 30000/**3000*/; i++) {
// distance = d.distance(t1, t2);
distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
}
double distanceTime = System.currentTimeMillis() - start;
System.out.println("Time: " + distanceTime/1000);
}
@SuppressWarnings("unused")
@Test
public void testDistance() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// -73.995008, 40.752842
t1.setValue(-73.995008, 40.752842);
// -73.994905, 40.752798
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-73.994905, 40.752798);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double distance = d.distance(t1, t2);
// assertTrue(isEqual(distance, 0));
// distance = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
// assertTrue(isEqual(distance, 0));
}
@Test
public void testSymmetric8() {
GeoSpatialFeature t1 = new GeoSpatialFeature();
// -73.995008, 40.752842
t1.setValue(-73.995008, 40.752842);
// -73.994905, 40.752798
GeoSpatialFeature t2 = new GeoSpatialFeature();
t2.setValue(-73.994905, 40.752798);
SphericalCosineDistance d = new SphericalCosineDistance(1);
double d1 = d.distance(t1, t2);
double d2 = d.distance(t2, t1);
assertTrue(isEqual(d1, d2));
d1 = d.aveMinDistance(Collections.singletonList(t1), Collections.singletonList(t2));
d2 = d.aveMinDistance(Collections.singletonList(t2), Collections.singletonList(t1));
assertTrue(isEqual(d1, d2));
}
}