Рисуем координаты на карте с помощью PHP + GDLib

    Так сложилось что по долгу своей службы я занимаюсь гео-поиском. И зачастую мне нужно показать на карте координаты пользователей, для того чтобы сделать какие-либо анализы. Для этой цели я, до определенного времени, успешно использовал Google Maps, пока, однажды, мне не понадобилось нанести на карту не много не мало 16 млн. координат.

    Как я это сделал?

    На ум сразу пришла библиотека DynamicDataDisplay, о которой писалось здесь не так давно. Но к сожалению нарисовать карту мне нужно было на Linux-сервере. Да и, вобщем-то если бы даже её и можно было запустить на линуксе — сделать это было бы крайне проблематично. Я решил не искать готового, а разобраться заодно с тем, что давно хотел сделать.

    Итак, нам понадобятся: PHP, GDLib и самая малость энциклопедических знаний.

    За знаниями отправляемся на Википедию. Вкратце расскажу теорию.

    Земля круглая, а мониторы плоские. Для того, чтобы можно было смотреть землю на мониторе — существуют методы проецирования земного шара на плоскость.
    Один из таких методов — проекция Герарда Меркатора, заключается в том что земной шар вытягивают в районе полюсов в цилиндр, а затем получившийся цилиндр разрезают по 180 меридиану в результате чего получается плоское изображение.

    Так как в районе полюсов карта получается очень растянутая, то небольшие куски сверху и снизу карты обрезаются (оставляют диапазон широт примерно от -85° до 85°). В итоге получается такая карта:



    На википедии можно скачать карту проекции Меркатора в высоком разрешении на которой мы и будем рисовать.

    Теперь как отобразить точку с заданной координатой на этой карте?
    Долгота в проекции Меркатора не искажается. Значит для того, чтобы узнать точку X на карте нам всего лишь нужно умножить долготу на масштаб карты по X и прибавить получившееся число к точке обозначающей середину карты.

    С широтой сложнее. Масштаб увеличивается от экватора к полюсам. Чем дальше от экватора — тем выше искажение.
    Увеличивается масштаб по такой формуле:



    Здесь φ — это широта (в радианах), y — коэффициент искажения.
    Зная это — умножаем широту на масштаб по Y и на коэффициент искажения.

    В качестве примера я сделал небольшой скрипт который рисует на карте точки. Там же можно найти несколько примеров использования.
    Мои 16 млн. координат я смог нанести на карту с помощью этого скрипта примерно за 2 минуты. Получилось примерно следующее:



    Спасибо за внимание.

    UPD: Пользователь axshavan в коментариях рассказал о равнопромежуточных проекциях.
    Доработал немного скрипт, добавил в него поддержку этой проекции.

    Вкратце отличия от проекции меркатора:

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

    Ссылки на скрипт:
    GeoMap.tgz (dropbox)
    GeoMap.tgz (google drive)

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 21

      –1
      Сколько времени уйдет на анализ перемещения 8 млн объектов?
        +2
        Сложно сказать. Все зависит от того что/кто, куда и как часто перемещается.
        • UFO just landed and posted this here
        +1
        Если не изобретать велосипед, то есть библиотека proj4.
        Да и земля круглая не у всех, у яндекс-карт уже используется эллипсоид.
          0
          Вот спасибо. Я в своё время криво-косо эту задачу решал, не дорешал толком :) Но у меня задача была другая, там допускалось.
            0
            Очень актуально! Задача состоит в том, чтобы на каждый времени была своя карта объектов. У меня 2.5 млн. объектов. Частоту обновление позиций нужно свести до максимума. ещё у меня карта в нескольких представлениях. Буду пробовать с PNG. Потом расскажу как вышло.
              +4
              Многие точки имеют одинаковые координаты или близкие (на карте они будут иметь одинаковую позицию). Сгруппировать такие точки можно ещё до отрисовки. Тогда на саму карту нужно будет нанести минимум обьектов и займет это намного меньше времени.
              0
              А никто не знает, где можно скачать карты в еще большем(намного) разрешении? Или может есть где их купить
                0
                Если нужны снимки, то landsat он public domain
                Если векторные карты, то openstreetmap
                  0
                  Насколько я понимаю опенстритмап по лицензии не позволяет использовать карты в коммерческих продуктах, хотя для внутреннего или free приминения — отличный вариант
                    0
                    Вы понимаете совершенно неправильно. Использовать в коммерческих продуктах можно, с указанием исходного авторства.
                    Monopoly City Streets например использовали данные от osm, сloud made опять-таки — все это коммерческие проекты.
                      0
                      Спасибо, копну поглубже
                0
                Зато для равнопромежуточной проекции с долготой проблем нет никаких, и даже можно с некоторой степенью уверенности нарисовать полюс.
                  0
                  Спасибо, широта действительно вычисляется проще. Обновил топик и скрипт.
                    0
                    А да, я перепутал широту и долготу в своём комментарии, прошу прощения. Но, как я вижу, вы меня поняли :)
                  –1
                  Ну раз уже пошла такая пьянка, то в проекции долгота-широта вообще никаких проблем нет с пересчетом )
                    0
                    Подождем сферических мониторов )
                  0
                  похоже на карту ботнета =)

                  Only users with full accounts can post comments. Log in, please.