Извлечение всех локаций в радиусе (Spring Boot) - PullRequest
0 голосов
/ 19 марта 2019

В настоящее время я пытаюсь разработать функциональность, при которой все местоположения в пределах определенного радиуса (например, в пределах 10 км) должны быть возвращены. Я использую пространственную зависимость hibernate. Вот как выглядит моя сущность:

public class LocationEntity {

@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Column(name = "LOCATION", columnDefinition = "geometry")
private Point location;
}

Это хранилище для сущности:

public interface LocationRepository extends JpaRepository<LocationEntity, Integer> {

@Query(value = "SELECT l from LocationEntity l WHERE within(l.location, :bounds) = true")
public List<LocationEntity> findWithin(@Param("bounds") Geometry bounds); }

Вот как вызывается метод хранилища:

GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
    shapeFactory.setNumPoints(100);
    shapeFactory.setCentre(new Coordinate(27.174835, 78.040753));
    shapeFactory.setSize(2*10);
    List<LocationEntity> locations = repository.findWithin(shapeFactory.createCircle());

Проблема, с которой я сталкиваюсь, заключается в том, что этот метод возвращает некоторые местоположения, которые не попадают в этот радиус. Это правильный подход для постановки задачи?

1 Ответ

0 голосов
/ 26 марта 2019

Наконец-то получил рабочее решение.Оставив мой подход здесь на случай, если кто-то еще столкнется с этой проблемой.Код получен из ответа на вопрос здесь .

final GeometricShapeFactory shape = new GeometricShapeFactory(new GeometryFactory());// INFO :jts lib
    GeometryFactory factory = new GeometryFactory();
    Point center = factory.createPoint(new Coordinate(latitude, longitude));
    center.setSRID(4326);

    final Coordinate centreInUTM = new Coordinate(projectedToGeographic(center.getX(), center.getY()));
    shape.setCentre(centreInUTM);
    shape.setSize(2 * radius);// distance in meters e.g 10000 for 10 km
    shape.setNumPoints(64);

    String UtmZone = degreeToUtmConverter(latitude, longitude);
    Integer longitudeZone = Integer.parseInt(UtmZone.split(",")[0]);
    char latitudeZone = UtmZone.split(",")[1].charAt(0);
    logger.info("longitude zone:" + longitudeZone);
    logger.info("latitude zone:" + latitudeZone);

    // WGS 1984 is a geographic coordinate system, and UTM is a projected coordinate
    // system
    Polygon polygon = new GeometryFactory().createPolygon(Arrays.stream(shape.createEllipse().getCoordinates())
            .map(c -> geographicToProjected(c.getOrdinate(0), c.getOrdinate(1), longitudeZone, latitudeZone)).toArray(Coordinate[]::new));

    List<LocationEntity> locations = repository.findWithin(polygon);

Добавлена ​​функция для преобразования широты / долготы в UTM широта / длинная зона, взятая из здесь

private Coordinate projectedToGeographic(double latitude, double longitude) {

    LatLong latlong = LatLong.valueOf(latitude, longitude, NonSI.DEGREE_ANGLE);

    UTM utm = UTM.latLongToUtm(latlong, ReferenceEllipsoid.WGS84); 

    double cX = utm.getCoordinates()[0];
    double cY = utm.getCoordinates()[1];

    return new Coordinate(cX, cY);
}

private Coordinate geographicToProjected(double easting, double northing, Integer longitudeZone, char latitudeZone) {
    UTM utm = UTM.valueOf(longitudeZone, latitudeZone, easting, northing, SI.METER);// INFO :18T UTM for NYC
    CoordinatesConverter<UTM, LatLong> utmToLatLong = UTM.CRS.getConverterTo(LatLong.CRS);
    LatLong latLong = utmToLatLong.convert(utm);

    double cX = latLong.getCoordinates()[0];
    double cY = latLong.getCoordinates()[1];

    return new Coordinate(cX, cY);
}

private String degreeToUtmConverter(double Lat, double Lon) {
    Integer zone;
    char letter;
    zone = (int) Math.floor(Lon / 6 + 31);
    if (Lat < -72)
        letter = 'C';
    else if (Lat < -64)
        letter = 'D';
    else if (Lat < -56)
        letter = 'E';
    else if (Lat < -48)
        letter = 'F';
    else if (Lat < -40)
        letter = 'G';
    else if (Lat < -32)
        letter = 'H';
    else if (Lat < -24)
        letter = 'J';
    else if (Lat < -16)
        letter = 'K';
    else if (Lat < -8)
        letter = 'L';
    else if (Lat < 0)
        letter = 'M';
    else if (Lat < 8)
        letter = 'N';
    else if (Lat < 16)
        letter = 'P';
    else if (Lat < 24)
        letter = 'Q';
    else if (Lat < 32)
        letter = 'R';
    else if (Lat < 40)
        letter = 'S';
    else if (Lat < 48)
        letter = 'T';
    else if (Lat < 56)
        letter = 'U';
    else if (Lat < 64)
        letter = 'V';
    else if (Lat < 72)
        letter = 'W';
    else
        letter = 'X';
    return zone.toString() + "," + letter;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...