Разделить область на земном шаре, заданную 4 координатами широты и долготы, на равноудаленную сетку?

Итак, я работаю над окончательным проектом на языке Java, в этом проекте есть серверная часть (за которую я отвечаю) и клиент с графическим интерфейсом (за который отвечает кто-то другой).

В качестве сервера я постоянно получаю GPS-координацию (как широту и долготу) от клиентов Android, и мне нужно ответить их эквивалентным местоположением в предварительно выделенной сетке.

Сетка задается 4 координатами LatLng, отправленными мне клиентом GUI, и количеством линий сетки, на которые нужно разделить. Например. Я получаю (35.000,35.000),(35.000,36.000),(36.000,36.000),(36.000,35.000) и 40x40.

Текущий метод, который я использую, заключается в вычислении расстояния в градусах радиана для расстояния по широте области и расстояния по долготе отдельно, а затем я делю его на 40 (как в приведенном примере), каждое частное — это мой «щелчок», единая единица расстояния, которую я использую позже.

Когда я получаю новую координату, я делю ее на свой «щелчок» и делаю Math.floor, частное этой операции - это местоположение на сетке. Но что-то не так, мои расчеты видимо неверны, так как GUI клиент со мной не согласен (обычно по 1 сетке север/юг и 1 сетка запад/восток, он просто берет карту (например гугл-карту) и манипулирует ею как картинкой просто разделение прямоугольной области.Что я делаю неправильно?Есть ли лучший способ дискретизации области, заданной этой установкой?

Вещи, которые я уже проверил: 1. Это не какое-то недополнение с плавающей запятой, я использовал BigDecimal и SimpleLatLng .

  1. Клиент с графическим интерфейсом соглашается со мной в местах, расположенных ближе к относительному блоку сетки 0x0, так что это не обычная ошибка смещения на единицу.

РЕДАКТИРОВАТЬ: мне удалось исправить большую часть ошибки, у меня все еще есть ошибка, за которую я не знаю, какая часть кода может быть ответственной.

РЕДАКТИРОВАТЬ 2: Проблема, кажется, решена, проблема заключалась в том, что в первую очередь не был получен правильный пеленг, и просто предполагалось, что сетка была привязана к северу, правильный код прилагается:


person Fanchi    schedule 09.01.2016    source источник
comment
Разделение в равноудаленной сетке сложное, для этого потребуется преобразование координат. Гораздо проще, в зависимости от приложения, разделить по ступеням. Тогда очень легко найти правильную ячейку сетки.   -  person AlexWien    schedule 11.01.2016


Ответы (1)


Мне удалось ответить себе после изучения и игры с кодом. Это окончательная реализация этого решения, используемого в коде наших проектов. Вы можете использовать его свободно и, надеюсь, он поможет другим в будущем:

import com.javadocmd.simplelatlng.LatLng;
import com.javadocmd.simplelatlng.LatLngTool;
import com.javadocmd.simplelatlng.util.LengthUnit;
import java.awt.*;
import java.util.LinkedList;
import java.util.List;

public class GridMap {
private double lat_rad;
private double lng_rad;
private Polygon grid;
private double factor = 100000;
private List<LatLng> bounds = new LinkedList<>();

public GridMap(int lat_bin, int lng_bin, List<Double> coords) {
    // coords should be (y_bot, x_bot;,y_up, x_bot;y_up, x_up;y_bot, x_up)
    grid = new Polygon();
    for (int i = 0; i < coords.size(); i += 2) {
        int nx = (int) Math.floor(factor * coords.get(i));
        int ny = (int) Math.floor(factor * coords.get(i + 1));
        grid.addPoint(nx, ny);
        bounds.add(new LatLng(coords.get(i), coords.get(i + 1)));
    }
    lat_rad = LatLngTool.distance(bounds.get(0), bounds.get(1), LengthUnit.METER) / (lat_bin);
    lng_rad = LatLngTool.distance(bounds.get(0), bounds.get(3), LengthUnit.METER) / (lng_bin);
}

public boolean inGrid(LatLng point) {
    int lat = (int) Math.floor(factor * point.getLatitude());
    int lng = (int) Math.floor(factor * point.getLongitude());
    return grid.contains(lat, lng);
}

public Point toGrid(LatLng llp) {
    if (inGrid(llp)) {
        double lat = llp.getLatitude();
        double lng = llp.getLongitude();
        double rel_lat = bounds.get(0).getLatitude();
        double rel_lng = bounds.get(0).getLongitude();
        int ilat = (int) Math.floor(LatLngTool.distance(new LatLng(rel_lat, lng), bounds.get(0), LengthUnit.METER) / lat_rad);
        int ilng = (int) Math.floor(LatLngTool.distance(new LatLng(lat, rel_lng), bounds.get(0), LengthUnit.METER) / lng_rad);
        return new Point(ilat, ilng);
    }
    return new Point(-1, -1);
}

public LatLng toLatLng(Point gridLoc){
    double lat_dist = (gridLoc.getY() + 0.5) * lat_rad;
    double lng_dist = (gridLoc.getX() + 0.5) * lng_rad;
    double y_bearing = LatLngTool.initialBearing(bounds.get(0), bounds.get(1));
    double x_bearing = LatLngTool.initialBearing(bounds.get(1), bounds.get(2));
    LatLng startLatLng = new LatLng(bounds.get(0).getLatitude(), bounds.get(0).getLongitude());
    LatLng lat_llp = LatLngTool.travel(startLatLng, y_bearing, lat_dist, LengthUnit.METER);
    return LatLngTool.travel(lat_llp, x_bearing, lng_dist, LengthUnit.METER);
}
}
person Fanchi    schedule 23.01.2016