diff --git a/src/main/java/org/springframework/data/geo/Distance.java b/src/main/java/org/springframework/data/geo/Distance.java index eb7086f93..7478c38e2 100644 --- a/src/main/java/org/springframework/data/geo/Distance.java +++ b/src/main/java/org/springframework/data/geo/Distance.java @@ -30,7 +30,7 @@ public class Distance { private final Metric metric; /** - * Creates a new {@link Distance}. + * Creates a new {@link Distance} with a neutral metric. This means the provided value needs to be in normalized form. * * @param value */ @@ -45,6 +45,7 @@ public class Distance { * @param metric can be {@literal null}. */ public Distance(double value, Metric metric) { + this.value = value; this.metric = metric == null ? Metrics.NEUTRAL : metric; } @@ -110,6 +111,19 @@ public class Distance { return new Distance(newLeft + newRight, metric); } + /** + * Returns a new {@link Distance} in the given {@link Metric}. This means that the returned instance will have the + * same normalized value as the original instance. + * + * @param metric must not be {@literal null}. + * @return + */ + public Distance in(Metric metric) { + + Assert.notNull(metric, "Metric must not be null!"); + return this.metric.equals(metric) ? this : new Distance(getNormalizedValue() * metric.getMultiplier(), metric); + } + /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) diff --git a/src/test/java/org/springframework/data/geo/DistanceUnitTests.java b/src/test/java/org/springframework/data/geo/DistanceUnitTests.java index 684e1da29..d6b27da30 100644 --- a/src/test/java/org/springframework/data/geo/DistanceUnitTests.java +++ b/src/test/java/org/springframework/data/geo/DistanceUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.geo; import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.number.IsCloseTo.*; import static org.junit.Assert.*; import static org.springframework.data.geo.Metrics.*; @@ -29,6 +30,10 @@ import org.junit.Test; */ public class DistanceUnitTests { + private static final double EPS = 0.000000001; + private static final double TEN_MILES_NORMALIZED = 0.002523219294755161; + private static final double TEN_KM_NORMALIZED = 0.001567855942887398; + /** * @see DATACMNS-437 */ @@ -62,4 +67,61 @@ public class DistanceUnitTests { assertThat(left.add(right, MILES), is(new Distance(3.106856281073925, MILES))); } + + /** + * @see DATACMNS-474 + */ + @Test + public void distanceWithSameMetricShoudEqualAfterConversion() { + + assertThat(new Distance(1).in(NEUTRAL), is(new Distance(1))); + assertThat(new Distance(TEN_KM_NORMALIZED).in(KILOMETERS), is(new Distance(10, KILOMETERS))); + assertThat(new Distance(TEN_MILES_NORMALIZED).in(MILES), is(new Distance(10, MILES))); + } + + /** + * @see DATACMNS-474 + */ + @Test + public void distanceWithDifferentMetricShoudEqualAfterConversion() { + + assertThat(new Distance(10, MILES), is(new Distance(TEN_MILES_NORMALIZED).in(MILES))); + assertThat(new Distance(10, KILOMETERS), is(new Distance(TEN_KM_NORMALIZED).in(KILOMETERS))); + } + + /** + * @see DATACMNS-474 + */ + @Test + public void conversionShouldProduceCorrectNormalizedValue() { + + assertThat(new Distance(TEN_KM_NORMALIZED, NEUTRAL).in(KILOMETERS).getNormalizedValue(), + closeTo(new Distance(10, KILOMETERS).getNormalizedValue(), EPS)); + + assertThat(new Distance(TEN_KM_NORMALIZED).in(KILOMETERS).getNormalizedValue(), + closeTo(new Distance(10, KILOMETERS).getNormalizedValue(), EPS)); + + assertThat(new Distance(TEN_MILES_NORMALIZED).in(MILES).getNormalizedValue(), + closeTo(new Distance(10, MILES).getNormalizedValue(), EPS)); + + assertThat(new Distance(TEN_MILES_NORMALIZED).in(MILES).getNormalizedValue(), + closeTo(new Distance(16.09344, KILOMETERS).getNormalizedValue(), EPS)); + + assertThat(new Distance(TEN_MILES_NORMALIZED).in(KILOMETERS).getNormalizedValue(), + closeTo(new Distance(10, MILES).getNormalizedValue(), EPS)); + + assertThat(new Distance(10, KILOMETERS).in(MILES).getNormalizedValue(), + closeTo(new Distance(6.21371192, MILES).getNormalizedValue(), EPS)); + } + + /** + * @see DATACMNS-474 + */ + @Test + public void toStringAfterConversion() { + + assertThat(new Distance(10, KILOMETERS).in(MILES).toString(), is(new Distance(6.21371256214785, MILES).toString())); + assertThat(new Distance(6.21371256214785, MILES).in(KILOMETERS).toString(), + is(new Distance(10, KILOMETERS).toString())); + } }