LINUX.ORG.RU

OSM ZoomLevels Scale

 , zoomlevels


0

1

Здравствуй дорогой LOR. Я вроде не извращенец, но тут мне подфартило.

Описываю ситуацию. Два года назад я решал эту проблему, но прошлые работодатели упорно не хотят давать взглянуть в код, говоря что это их технологии, а сейчас мне нужно написать то же самое, но времени почти нет. В тот раз я решал проблему на фултайм 2 недели.

Проблема в следующем. Есть набор маркеров на карте (1-100). Вычисляем максимальную и минимальную (Lat,Lon), определяем прямоугольник в который входят все точки. Получилась фигура например 100 на 200 километров. Доступная площадь экрана 800 на 600 пикселей.

Теперь нужно посчитать ZoomLevel, чтобы все точки гарантированно попадали в поле видимости.

И тут начинается темный лес.

Я не вспомню как я пользовался этим

http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

и этим

http://wiki.openstreetmap.org/wiki/Zoom_levels

для расчетов.

Вроде нужно определить DPI экрана. Как это сделать?

Далее нужно связать DPI и максимальное расстояние которое нужно отобразить. Тоже пока не понял.

После этого можно выйти на ZoomLevel. Хорошо если кому то все понятно, помогите разобраться и мне. Обещаю код написанный мной оставить здесь для потомков.

★★

Последнее исправление: weare (всего исправлений: 3)

Ну это просто

Вычисляешь координаты прямоугольника в градусах
На каждом уровне масштаба с максимально доступного (19 вроде - тут у разных систем (и в разных областях) по-разному) переводишь эти координаты в пиксели (с учетом типа проекции и датума (привязки)), уменьшая уровень до тех пор, пока не влезет в экран.

Uter
()
Последнее исправление: Uter (всего исправлений: 1)
Ответ на: комментарий от Uter

А размер экрана в максимально доступные координаты ты не переведешь, так как чем больше широта - тем больше пикселей на километр требуется (в меркаторе)

Uter
()

В тот раз я решал проблему на фултайм 2 недели.

Ты смеёшься наверное, да?

Далее нужно связать DPI и максимальное расстояние которое нужно отобразить. Тоже пока не понял.

Зачем тебе DPI когда тайлы сделаны из пикселей и размеры экрана заданы в пикселях?

Считаешь нужное разрешение по горизонтали/вертикали - размер экрана/размер прямоугольника в пикселах/км.

Разрешение каждого зума в тех же единицах = резмер тайла (256) * 2**zoom / длина параллели.

Осталось найти максимальный зум, на когорый хватит разрешения, циклом или round'ом, на что мозгов хватит.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

Попробую завтра переложить в код формулу, хотя я ее до сих пор плохо понимаю, но раз речь идет о подборе значения, то уже яснее.

weare ★★
() автор топика
Ответ на: комментарий от Uter

Спасибо, попробую переложить в код. Так будет более конкретный разговор.

weare ★★
() автор топика
Ответ на: комментарий от Uter

Сейчас получился такой код, он почти рабочий. Код на JavaScript

    function SetFocus() {
        var ZoomLevelResolution = [156412, 78206, 39103, 19551, 9776, 4888, 2444, 1222, 610.984, 305.492, 152.746, 76.373, 38.187, 19.093, 9.547, 4.773, 2.387, 1.193, 0.596, 0.298]

        var MaxLat = -90;
        var MinLat = 90;
        var MaxLon = 0;
        var MinLon = 180;
        for (var i = 0; i < CarInfoFromServer.length; i++) {
            if (CarInfoFromServer[i].Lat > MaxLat) MaxLat = CarInfoFromServer[i].Lat;
            if (CarInfoFromServer[i].Lat < MinLat) MinLat = CarInfoFromServer[i].Lat;
            if (CarInfoFromServer[i].Lon > MaxLon) MaxLon = CarInfoFromServer[i].Lon;
            if (CarInfoFromServer[i].Lon < MinLon) MinLon = CarInfoFromServer[i].Lon;
        }

        var AvgLat = (MaxLat + MinLat) / 2;
        var AvgLon = (MaxLon + MinLon) / 2;


        var d_w = GetDistance(MaxLat, MinLon, MaxLat, MaxLon);
        var d_h = GetDistance(MinLat, MinLon, MaxLat, MinLon);
        var Distance = 0;
        if (d_w > d_h) Distance = d_w; else Distance = d_h;
        var Pixels = 0;
        if (map_w > map_h) Pixels = map_h; else Pixels = map_w;
        var Resolution = Distance / Pixels;
        var ZoomLevel = 0;
        for (var i = 0; i < ZoomLevelResolution.length; i++) {
            if (Resolution > ZoomLevelResolution[i]) {
                ZoomLevel = i - 1;
                break;
            }
        }
        map.setView([AvgLat, AvgLon], ZoomLevel);
    }
weare ★★
() автор топика
Последнее исправление: weare (всего исправлений: 1)
Ответ на: комментарий от weare

Смотри внимательно api у Leaflet (ты ведь им пользуешься). Там должен быть метод который принимает границы видимой области в географических координатах. Документацию OSM тебе не нужно читать, читай документацию библиотеки, которую используешь, она сама разберется, как ей тайлы выкачать из osm, MapServer'а или любого другого источника геоданных, который ты задашь.

nguseff
()
Ответ на: комментарий от slovazap

За аудитом кода - в раздел Job.

Это вообще уникальный экземпляр. LOR-based development какой-то. На каждый чих - новая тема.

nguseff
()
Ответ на: комментарий от nguseff

А что, пока я читаю, пусть другие подумают))) Дело в том что у Leaflet обширная документация, да и у OSM не маленькая.

Например зависимость в формуле предложенную выше я не понял.

weare ★★
() автор топика
Ответ на: комментарий от slovazap

Просто сейчас я работаю админом, а кодинг для души, поэтому нет желания гробить все свободное время на изучение предмета, лучше спросить, а свободного времени и так мало...

weare ★★
() автор топика
Ответ на: комментарий от weare

Вы сами себе противоречите. Когда «для души», изучение является первостепенной целью, времени жалко не бывает и уж точно не возникает желания чтобы что-то делали за тебя.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Никакого противоречия, просто если решение задачи вызывает чувство безысходности, то ни о каком удовольствии речь уже не идет. Лучше спросить.

Кроме того более опытные разработчики предлагают более прямые пути решения, а я иногда придумываю велосипед.

Вот и сейчас я решил задачу по своему, боюсь оно не будет идеальным на всем множестве масштабов, но пока пойдет. Пока займусь вопросами ASP NET, но это уже совсем другая история.

Кстати почему Apache не поддерживает ASP, когда исходники фреймворка открыты, может Вы в курсе?

weare ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.