prepping for antimeridian test
This commit is contained in:
parent
11dc087750
commit
72ccd76ed0
|
@ -4,12 +4,14 @@ import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.CoordCalculator;
|
||||
import ca.uhn.fhir.jpa.util.SearchBox;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
import ca.uhn.fhir.rest.param.SpecialParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import org.hibernate.search.spatial.impl.Point;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@ -25,6 +27,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
@Component
|
||||
@Scope("prototype")
|
||||
public class PredicateBuilderCoords extends BasePredicateBuilder implements IPredicateBuilder {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(PredicateBuilderCoords.class);
|
||||
|
||||
PredicateBuilderCoords(SearchBuilder theSearchBuilder) {
|
||||
super(theSearchBuilder);
|
||||
|
@ -84,22 +87,25 @@ public class PredicateBuilderCoords extends BasePredicateBuilder implements IPre
|
|||
longitudePredicate = theBuilder.equal(theFrom.get("myLongitude"), longitudeValue);
|
||||
} else if (distanceKm < 0.0) {
|
||||
throw new IllegalArgumentException("Invalid " + Location.SP_NEAR_DISTANCE + " parameter '" + distanceKm + "' must be >= 0.0");
|
||||
} else if (distanceKm > CoordCalculator.MAX_SUPPORTED_DISTANCE_KM) {
|
||||
throw new IllegalArgumentException("Invalid " + Location.SP_NEAR_DISTANCE + " parameter '" + distanceKm + "' must be <= " + CoordCalculator.MAX_SUPPORTED_DISTANCE_KM);
|
||||
} else {
|
||||
double latitudeDegrees = Double.parseDouble(latitudeValue);
|
||||
double longitudeDegrees = Double.parseDouble(longitudeValue);
|
||||
|
||||
Point northPoint = CoordCalculator.findTarget(latitudeDegrees, longitudeDegrees, 0.0, distanceKm);
|
||||
Point eastPoint = CoordCalculator.findTarget(latitudeDegrees, longitudeDegrees, 90.0, distanceKm);
|
||||
Point southPoint = CoordCalculator.findTarget(latitudeDegrees, longitudeDegrees, 180.0, distanceKm);
|
||||
Point westPoint = CoordCalculator.findTarget(latitudeDegrees, longitudeDegrees, 270.0, distanceKm);
|
||||
SearchBox box = CoordCalculator.getBox(latitudeDegrees, longitudeDegrees, distanceKm);
|
||||
|
||||
// FIXME KHS
|
||||
ourLog.info("Searching for {} =< latitude <= {}", box.getSouthWest().getLatitude(), box.getNorthEast().getLatitude());
|
||||
latitudePredicate = theBuilder.and(
|
||||
theBuilder.greaterThanOrEqualTo(theFrom.get("myLatitude"), southPoint.getLatitude()),
|
||||
theBuilder.lessThanOrEqualTo(theFrom.get("myLatitude"), northPoint.getLatitude())
|
||||
theBuilder.greaterThanOrEqualTo(theFrom.get("myLatitude"), box.getSouthWest().getLatitude()),
|
||||
theBuilder.lessThanOrEqualTo(theFrom.get("myLatitude"), box.getNorthEast().getLatitude())
|
||||
);
|
||||
// FIXME KHS
|
||||
ourLog.info("Searching for {} =< longitude <= {}", box.getSouthWest().getLongitude(), box.getNorthEast().getLongitude());
|
||||
longitudePredicate = theBuilder.and(
|
||||
theBuilder.greaterThanOrEqualTo(theFrom.get("myLongitude"), westPoint.getLongitude()),
|
||||
theBuilder.lessThanOrEqualTo(theFrom.get("myLongitude"), eastPoint.getLongitude())
|
||||
theBuilder.greaterThanOrEqualTo(theFrom.get("myLongitude"), box.getSouthWest().getLongitude()),
|
||||
theBuilder.lessThanOrEqualTo(theFrom.get("myLongitude"), box.getNorthEast().getLongitude())
|
||||
);
|
||||
}
|
||||
Predicate singleCode = theBuilder.and(latitudePredicate, longitudePredicate);
|
||||
|
|
|
@ -4,9 +4,11 @@ package ca.uhn.fhir.jpa.util;
|
|||
import org.hibernate.search.spatial.impl.Point;
|
||||
|
||||
public class CoordCalculator {
|
||||
public static final double RADIUS_EARTH_KM = 6378.1;
|
||||
public static final double MAX_SUPPORTED_DISTANCE_KM = 10000.0; // Slightly less than a quarter of the earth's circumference
|
||||
private static final double RADIUS_EARTH_KM = 6378.1;
|
||||
|
||||
public static Point findTarget(double theLatitudeDegrees, double theLongitudeDegrees, double theBearingDegrees, double theDistanceKm) {
|
||||
// Source: https://stackoverflow.com/questions/7222382/get-lat-long-given-current-point-distance-and-bearing
|
||||
static Point findTarget(double theLatitudeDegrees, double theLongitudeDegrees, double theBearingDegrees, double theDistanceKm) {
|
||||
|
||||
double latitudeRadians = Math.toRadians(theLatitudeDegrees);
|
||||
double longitudeRadians = Math.toRadians(theLongitudeDegrees);
|
||||
|
@ -21,4 +23,16 @@ public class CoordCalculator {
|
|||
|
||||
return Point.fromDegrees(Math.toDegrees(targetLatitude), Math.toDegrees(targetLongitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a box around my coordinates such that the closest distance to each edge is the provided distance
|
||||
*/
|
||||
public static SearchBox getBox(double theLatitudeDegrees, double theLongitudeDegrees, Double theDistanceKm) {
|
||||
double diagonalDistanceKm = theDistanceKm * Math.sqrt(2.0);
|
||||
|
||||
Point northEast = CoordCalculator.findTarget(theLatitudeDegrees, theLongitudeDegrees, 45.0, diagonalDistanceKm);
|
||||
Point southWest = CoordCalculator.findTarget(theLatitudeDegrees, theLongitudeDegrees, 225.0, diagonalDistanceKm);
|
||||
|
||||
return new SearchBox(southWest, northEast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
import org.hibernate.search.spatial.impl.Point;
|
||||
|
||||
public class SearchBox {
|
||||
private final Point mySouthWest;
|
||||
private final Point myNorthEast;
|
||||
|
||||
public SearchBox(Point theSouthWest, Point theNorthEast) {
|
||||
mySouthWest = theSouthWest;
|
||||
myNorthEast = theNorthEast;
|
||||
}
|
||||
|
||||
public Point getSouthWest() {
|
||||
return mySouthWest;
|
||||
}
|
||||
|
||||
public Point getNorthEast() {
|
||||
return myNorthEast;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,43 @@ public class CoordCalculatorTest {
|
|||
Point result = CoordCalculator.findTarget(LATITUDE_CHIN, LONGITUDE_CHIN, BEARING_CHIN_TO_UHN, DISTANCE_KM_CHIN_TO_UHN);
|
||||
|
||||
assertEquals(LATITUDE_UHN, result.getLatitude(), 0.0001);
|
||||
assertEquals(LONGITUDE_UHN, result.getLatitude(), 0.0001);
|
||||
assertEquals(LONGITUDE_UHN, result.getLongitude(), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBox() {
|
||||
SearchBox box = CoordCalculator.getBox(LATITUDE_CHIN, LONGITUDE_CHIN, 1.0);
|
||||
double expectedLatitudeDelta = 0.0090;
|
||||
assertEquals(LATITUDE_CHIN - expectedLatitudeDelta, box.getSouthWest().getLatitude(), 0.0001);
|
||||
assertEquals(LATITUDE_CHIN + expectedLatitudeDelta, box.getNorthEast().getLatitude(), 0.0001);
|
||||
double expectedLongitudeDelta = 0.012414;
|
||||
assertEquals(LONGITUDE_CHIN - expectedLongitudeDelta, box.getSouthWest().getLongitude(), 0.0001);
|
||||
assertEquals(LONGITUDE_CHIN + expectedLongitudeDelta, box.getNorthEast().getLongitude(), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPrimeMeridian() {
|
||||
double meridianLongitide = 0.0;
|
||||
SearchBox box = CoordCalculator.getBox(LATITUDE_CHIN, meridianLongitide, 1.0);
|
||||
double expectedLatitudeDelta = 0.0090;
|
||||
assertEquals(LATITUDE_CHIN - expectedLatitudeDelta, box.getSouthWest().getLatitude(), 0.0001);
|
||||
assertEquals(LATITUDE_CHIN + expectedLatitudeDelta, box.getNorthEast().getLatitude(), 0.0001);
|
||||
double expectedLongitudeDelta = 0.012414;
|
||||
assertEquals(meridianLongitide - expectedLongitudeDelta, box.getSouthWest().getLongitude(), 0.0001);
|
||||
assertEquals(meridianLongitide + expectedLongitudeDelta, box.getNorthEast().getLongitude(), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAntiMeridian() {
|
||||
double antiMeridianLongitide = 180.0;
|
||||
SearchBox box = CoordCalculator.getBox(LATITUDE_CHIN, antiMeridianLongitide, 1.0);
|
||||
double expectedLatitudeDelta = 0.0090;
|
||||
assertEquals(LATITUDE_CHIN - expectedLatitudeDelta, box.getSouthWest().getLatitude(), 0.0001);
|
||||
assertEquals(LATITUDE_CHIN + expectedLatitudeDelta, box.getNorthEast().getLatitude(), 0.0001);
|
||||
double expectedLongitudeDelta = 0.012414;
|
||||
assertEquals(antiMeridianLongitide - expectedLongitudeDelta, box.getSouthWest().getLongitude(), 0.0001);
|
||||
// This case wraps
|
||||
assertEquals(antiMeridianLongitide + expectedLongitudeDelta - 360.0, box.getNorthEast().getLongitude(), 0.0001);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,10 +67,6 @@ public class SearchParamExtractorService {
|
|||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, uris);
|
||||
theParams.myUriParams.addAll(uris);
|
||||
|
||||
// ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamCoords> coords = extractSearchParamCoords(theResource);
|
||||
// handleWarnings(theRequestDetails, myInterceptorBroadcaster, coords);
|
||||
// theParams.myCoordsParams.addAll(coords);
|
||||
|
||||
ourLog.trace("Storing date indexes: {}", theParams.myDateParams);
|
||||
|
||||
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theResource)) {
|
||||
|
|
Loading…
Reference in New Issue