Я искал надежное решение, которое позволило бы мне создать веб-карту и наложить векторные многоугольники, не затрачивая на это вечную загрузку таких данных, чтобы позволить каждому полигону отображать свой цвет при событии наведения мыши.
Насколько мне известно, есть 3 варианта для достижения этой цели с помощью Canvas, SVG, Flash.
Похоже, что Flash будет лучшим решением, если он будет работать на Apple iPhone / iPad, так как он обеспечивает самый быстрый рендеринг и самый чистый дисплей. Canvas, кажется, второй лучший выбор, но он занимает ОЧЕНЬ много времени, если на карте отображаются сотни полигонов, тогда как SVG визуализируется еще дольше.
Я почти потерял надежду в поиске решения этой проблемы, но сегодня я наткнулся на компанию GISCloud http://www.giscloud.com (в настоящее время в бета-версии с бесплатной регистрацией).
Этой компании SOMEHOW удалось найти удивительный способ визуализации сотен векторов на карте в режиме реального времени. Я был поражен их подходом, и мой вопрос к сообществу касается того, как мы можем воспроизвести их подход для использования с существующими технологиями, такими как листовка, открытые слои, воск ...
Посмотрите сами на это удивительное демо: http://www.giscloud.com/map/284/africa
Убедитесь, что вы наводите курсор на любой из многоугольников на странице, и проверьте элементы управления масштабированием, чтобы убедиться, что эти многоугольники действительно являются векторами.
Что я заметил, глядя на запросы с firebug, так это то, что карта запрашивает определенные файлы json. Кажется, что в зависимости от уровня / области масштабирования запрашиваются несколько файлов json.
Я должен также упомянуть, что когда giscloud загружает данные на странице, нависающей над вектором, немедленно меняет цвет, не создавая новый запрос.
ПРИМЕРЫ:
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/3/3.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/3.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/4/4.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/3/4.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/4.json
Я предполагаю, что структура URL соответствует стандартной логике службы листов (например, папка с 3-й по последнюю очередь является уровнем масштабирования ...).
В любом случае я проанализировал фактические данные этих файлов json, и кажется, что логика, которую они используют, следует некоторой логике, с помощью которой они создают свои векторы, основываясь только на этих значениях данных:
- ширина / высота: они определяют ширину и высоту данных, обслуживаемых в каждом запросе json
- пиксели: здесь они определяют значения пикселей, которые, как я предполагаю, как-то связаны с некоторыми общими координатами пикселей x / y для обобщенных уровней точек? Я предполагаю, что у них есть способ автоматически упростить регион в зависимости от уровня масштабирования. Я предполагаю, что они используют координаты пикселей. Я предполагаю, что они значительно уменьшают размер данных, которые должны быть загружены, по сравнению с данными широты / долготы.
- стили: здесь они определяют два значения RGB CSS. «F» представляет цвет файла полигона и «S» представляет цвет границы полигона.
- geom: здесь я предполагаю, что они каким-то образом определяют конкретное определение каждого полигона в загружаемом тайле, где такие данные определяются на основе окна контейнера карты. Также интересно то, что каждая запись имеет значение «S», которое, как я полагаю, используется в качестве необязательного значения атрибута или ссылки на функцию, и в конце каждой записи здесь есть область, которая, кажется, определяет конкретный идентификатор для каждого вектора вместе с идентификатор слоя, который, как я догадываюсь, используется для того, чтобы каким-то образом объединить данные из каждого вызываемого запроса мозаики json.
Я также предполагаю, что они каким-то образом нашли способ автоматического определения и разделения данных, которые должны быть загружены для каждой плитки, в зависимости от размера данных, которые должны быть загружены для запрошенной плитки.
Вот извлеченная разбивка одного из этих запросов:
{"width":256,"height":256,"tile":
{"pixels":
[0,6461,-1,0,5,148,0,509,-1,10715,-1,1,-1,251,-1,1,-1,1,-1,251,-2,3,-1,255,-1,249,-2,5,-2,247,-1,509,-3,251,-1,2,-2,253,-2,252,-2,254,-1,255,-1,254,-1,255,-1,1276,-2,13,-1,233,-1,2,-1,253,-1,1,-1,255,-1,247,-1,1306,-1,1533,-1,1269,-1,1276,-1,2303,-1]},
"styles":
[{"f":"rgb(99,230,101)","s":"rgb(5,148,0)","lw":"0"}],
"geom":
[
{"s":0,"p":[4,143,5,144,3,146,1,146,2,143,4,143],"c":"layer1156_5098"},
{"s":0,"p":[-2,143,0,140,2,141,2,144,1,146,-2,144,-2,143],"c":"layer1156_5067"},
{"s":0,"p":[7,143,5,144,4,143,2,143,2,141,5,138,6,139,5,141,7,143],"c":"layer1156_5051"},
{"s":0,"p":[10,141,11,137,12,137,14,137,12,142,9,143,9,142,10,141],"c":"layer1156_5041"},
{"s":0,"p":[1,136,0,140,-2,143,-2,136,1,136],"c":"layer1156_5038"},
{"s":0,"p":[8,143,5,141,5,137,8,136,10,137,10,141,8,143],"c":"layer1156_5033"},
{"s":0,"p":[5,137,2,141,0,140,1,136,1,136,2,135,3,136,5,137],"c":"layer1156_5028"},
{"s":0,"p":[10,134,12,136,11,138,8,135,10,134],"c":"layer1156_5020"},
{"s":0,"p":[-2,133,0,136,-2,136,-2,133],"c":"layer1156_5005"},
{...}
...
]
}
Как мы можем воспроизвести такой же (или похожий) тип скорости, используя postgis (который, как мне кажется, они также используют)?
источник
Ответы:
Я видел эту технику в прошлом. Это объяснил мне Зейн Мемон (из Trulia), который помог мне внести свой вклад, когда Михал Мигурски создавал TileStache. Заин рассказал об этом в своей демонстрации Trulia, которая использует эту технику на одном из наших старых совещаний SF GeoMeetup . На самом деле, если вы будете в SF на следующей неделе (это моя неудачная попытка подключиться к сети, он затронет это , так что не стесняйтесь появляться :)
Хорошо, теперь к объяснению.
Во-первых, вы смотрите немного не в том месте, когда смотрите на файлы json выше.
Позвольте мне объяснить (так коротко, как я могу), почему.
Плитки передаются так же, как и обычные отрисованные плитки, ничего страшного в этом нет, мы знаем, как это сделать, и поэтому мне не нужно это объяснять.
Если вы проверите его в Firebug, вы увидите, что вы также получите целую кучу изображений, которые кажутся пустыми, как этот .
Почему это пусто? Это не так. Пиксели содержат данные - просто не традиционные данные видимого изображения. Они используют очень умную технику для передачи данных, закодированных в самих пикселях.
В последнее десятилетие происходило то, что люди теряли удобочитаемость и переносимость данных форматов за счет эффективности хранения.
Возьмите этот пример данных примера xml:
Хорошо, сколько укусов, чтобы передать это? При условии, что мы имеем utf8 (1 байт на символ при работе с этим контентом). Ну, у нас есть около 176 символов (без учета табуляции или пробелов), что составляет 176 байтов (это оптимистично по разным причинам, которые я опущу для простоты). Имейте в виду, это за 2 балла!
Тем не менее, какая-то умная задница, которая где-то не понимает, о чем говорит, будет утверждать, что «json дает вам более высокое сжатие».
Хорошо, давайте поместим ту же ерунду xml, что и json:
Сколько здесь байтов? Скажите ~ 115 символов. Я даже немного обманул и сделал его меньше.
Скажем, моя область покрывает 256x256 пикселей, и я нахожусь на таком высоком уровне масштабирования, что каждая функция отображается как один пиксель, а у меня так много функций, что она заполнена. Сколько данных мне нужно, чтобы показать, что 65 536 функций?
54 символа (или UTF-байтов - и я даже игнорирую некоторые другие вещи) на каждую «функциональную» запись умножается на 65 536 = 3 538 944 или около 3,3 МБ
Я думаю, вы поняли картину.
Но так мы транспортируем данные в сервис-ориентированной архитектуре. Читаемая раздутая чушь.
Что если бы я хотел перенести все в бинарную схему, которую сам придумал? Скажем, вместо этого я закодировал эту информацию в одноканальном изображении (то есть в черно-белом). И я решил, что 0 означает продано, а 1 означает наличие, а 2 означает, что я не знаю. Черт, в 1 байте у меня есть 256 опций, которые я могу использовать - и я использую только 2 или три из них для этого примера.
Какова стоимость хранения этого? 256x256x 1 (только одна полоса). 65 536 байт или 0,06 МБ. И это даже не принимает во внимание другие методы сжатия, которые я получаю бесплатно после нескольких десятилетий исследований в области сжатия изображений.
На этом этапе вы должны спросить себя, почему люди не просто отправляют данные, закодированные в двоичном формате, вместо сериализации в json? Ну, во-первых, оказывается, javascript отнимает много времени для транспортировки двоичных данных , поэтому люди исторически этого не делали.
Некоторые люди использовали удивительную работу вокруг, когда появились новые функции HTML5, в частности, canvas . Так что же это за крутой обходной путь? Оказывается, вы можете отправлять данные по проводам, закодированным на то, что выглядит как изображение, а затем вы можете вставить это изображение в холст HTML5, что позволяет вам напрямую манипулировать пикселями ! Теперь у вас есть способ получить эти данные, декодировать их на стороне клиента и сгенерировать объекты json на клиенте.
Остановись и подумай об этом.
У вас есть способ кодировать огромное количество значимых данных с географической привязкой в сильно сжатом формате, на несколько порядков меньше, чем все, что традиционно делается в веб-приложениях, и манипулировать ими в javascript.
Холст HTML даже не нужно использовать для рисования, он используется только как механизм двоичного декодирования!
Вот о чем все эти изображения, которые вы видите в Firebug. Одно изображение с данными, закодированными для каждой загружаемой плитки. Они очень маленькие, но у них есть значимые данные.
Итак, как вы кодируете их на стороне сервера? Что ж, вам нужно обобщить данные на стороне сервера и создать значимую плитку для каждого уровня масштабирования, в котором закодированы данные. В настоящее время для этого вам нужно развернуть свое собственное решение - готового решения с открытым исходным кодом не существует, но у вас есть все инструменты, необходимые для этого. PostGIS выполнит обобщение через GEOS, TileCache можно использовать для кеширования и помочь вам запустить генерацию плиток. На клиентской стороне вам нужно будет использовать HTML5 Canvas для передачи специальных «поддельных плиток», а затем вы можете использовать OpenLayers для создания реальных клиентских JavaScript-объектов, которые представляют векторы с эффектами наведения мыши.
Если вам нужно кодировать больше данных, помните, что вы всегда можете генерировать изображения RGBA на пиксель (что дает вам 4 байта на пиксель или 4 294 967 296 чисел, которые вы можете представить на пиксель ). Я могу придумать несколько способов использовать это :)
Обновление : ответ на вопрос QGIS ниже.
QGIS, как и большинство других настольных ГИС , не имеет фиксированного набора уровней масштабирования. У них есть гибкость масштабирования в любом масштабе и просто рендеринга. Могут ли они отображать данные из источников на основе WMS или тайлов? Конечно, они могут, но в большинстве случаев они действительно глупы: увеличьте масштаб в другой степени, вычислите ограничивающую рамку, вычислите требуемые плитки, возьмите их, покажите их. Большую часть времени они игнорируют другие вещи, такие как кэши заголовков http, которые делают это так, чтобы им не приходилось обновляться. Иногда они реализуют простой механизм кэширования (сохраните плитку, если вы просите ее, проверьте плитку, не просите ее). Но этого недостаточно.
С этой техникой плитки и векторы должны быть повторно получены на каждом уровне масштабирования . Почему? Потому что векторы были обобщены, чтобы приспособить уровни масштабирования.
Что касается всего трюка с размещением плиток на холсте HTML5, чтобы вы могли получить доступ к буферам, то в этом нет необходимости. QGIS позволяет вам писать код на Python и C ++, оба языка имеют отличную поддержку для обработки двоичных буферов, поэтому этот обходной путь действительно не имеет значения для этой платформы.
* ОБНОВЛЕНИЕ 2 **:
Возник вопрос о том, как в первую очередь создать обобщенные векторные плитки (шаг 1, прежде чем можно будет сериализовать результаты в изображения). Возможно, я не уточнил достаточно. Tilestache позволит вам создавать эффективные «векторные плитки» ваших данных на каждом уровне масштабирования (у него даже есть опция, которая позволяет либо обрезать, либо не обрезать данные, когда они пересекают границу плитки). Это позволяет разделить векторы на плитки с различными уровнями масштабирования. Я бы выбрал опцию «не обрезать» (но она выберет произвольную плитку там, где она занимает большую площадь). Затем вы можете подать каждый вектор через опцию GEOS generalize с большим числом, фактически вы хотите, чтобы он был достаточно большим, чтобы полилинии и полигоны сваливались на себя, потому что если они это сделают, вы можете удалить их с уровня масштабирования, поскольку для этого этапа они не имеет значения. Tilestache даже позволяет вам писать простых питонических поставщиков данных, где вы можете использовать эту логику. На этом этапе вы можете использовать их как файлы json (как они делают с некоторыми образцами африканских карт) или как сериализованные геометрии в pngs, как они делают в других образцах (или Trulia), которые я дал выше.
источник
Непосредственно от разработчика Дино Равника в недавнем сообщении списка рассылки :
Похоже, что клиентская часть - это легкая часть. Впечатляет, что данные отображаются без кеширования.
Он также упоминает хостинг, который может вас заинтересовать. Возможно, вы захотите взвесить стоимость попыток воссоздать это со стоимостью использования готового сервиса.
источник
Как я описал в списке OSGeo, ключом является предоставление данных в виде векторных плиток JSON, которые имеют пиксели для подпиксельной геометрии и обобщенной геометрии для тех объектов, которые фактически будут видны на определенном уровне. Производительность велика, потому что этот метод устраняет всю ненужную векторную информацию и оставляет только те векторы, которые фактически будут визуально влиять на карту. Пиксели предназначены для заполнения промежутков и размещения вместо этих подпиксельных векторов. Вот и все, что касается формата плитки.
На бэкэнде находится настоящий тяжелый груз. Мы не используем TileStache или какой-либо другой движок карт, так как мы написали наш собственный, который может с помощью ряда оптимизаций производить такую векторную графику в режиме реального времени.
Сначала мы начали с доставки листов карты в виде SWF-файлов, а в последнее время мы просто включили вывод в JSON, чтобы мы могли использовать HTML5 Canvas для визуализации графики. Ниже вы можете найти тест, сравнивающий этот вид векторной технологии с растровой технологией (mapnik). Для достоверного сравнения ищите результаты только в режиме CGI.
http://www.giscloud.com/blog/realtime-map-tile-rendering-benchmark-rasters-vs-vectors/
Мы планируем предоставить эту технологию в качестве хостинга картографических плиток. Идея состоит в том, чтобы разместить ваши геоданные в облаке и с помощью HTML5 доставить их в любой клиент карты на высокой скорости, без необходимости предварительно кэшировать плитки. Если вы заинтересованы присоединиться к этой бета-версии, не стесняйтесь связаться с нами здесь: http://www.giscloud.com/contact/
источник
Похоже, очень похожий вопрос был недавно задан на форуме OSGeo Open Layers , где разработчики GIS Cloud описывают свой подход, представляющий собой интересное сочетание геометрии GeoJSON и статических пикселей. Они на самом деле генерируют все векторные плитки на лету, а не используют предварительно созданный кэш файлов GeoJSON.
Esri реализовал аналогичный подход, используя ArcGIS Server и Feature Layers , которые могут обобщать геометрии на лету и отправлять их по проводам в формате JSON.
Для прямого метода, который вы можете реально реализовать сейчас, вы можете создавать векторные плитки с помощью Tilestache (с поддержкой PostGIS ) и использовать их в Polymaps . Polymaps использует SVG, но производительность довольно хорошая , и CSS-правила управляют стилем элементов карты, поэтому отрисовка объектов полностью зависит от вас. Вот сообщение в блоге, прорабатывающее что-то похожее на то, что вы просите
источник
Я поиграл с OpenLayers с использованием Canvas и получил разумные результаты.
Как упоминалось в других ответах: чтобы доставлять и показывать векторы на лету, их необходимо обобщать для каждого уровня масштабирования и каждого набора данных. Кроме того, вы можете использовать полилинию Google, чтобы значительно уменьшить размер.
Я использовал простой механизм доставки. Каждая геометрия была функцией JavaScript в ответе HTTP HTTP. не такой продвинутый, как доставка векторов на основе плиток, но простой и открытый исходный код!
Я не смог попробовать Google Maps v3 с Canvas, но видел несколько демонстраций New York Times, которые впечатлили.
источник
Я не знаю точно, какое решение использует эта компания (вы могли бы спросить их напрямую), но у меня есть идея.
Ключевое решение для улучшения скорости передачи по сети и рендеринга векторных данных заключается в их обобщении в соответствии с уровнем масштабирования. Передача и рендеринг с высоким уровнем масштабирования для тысяч объектов, рассчитанных на значительно более низкий уровень масштабирования, часто занимает очень много времени (а также бесполезно, потому что окончательное отображение обычно не читается - см., например, это изображение ). Чтобы реализовать это, ваша база данных Postgis-сервера должна быть многомасштабной : для каждого уровня масштабирования должно быть одно представление объекта, подходящее для этого уровня масштабирования. Эти различные представления могут быть вычислены автоматически с использованием методов обобщения, Кроме того, векторные данные, отправляемые сервером клиенту, должны зависеть не только от пространственного расширения, но и от уровня масштабирования: сервер отправляет подходящие данные в зависимости от уровня масштабирования. Этот подход защищен в этой превосходной статье :-)
источник
Есть интересная статья, демонстрация и исходный код программного обеспечения, разработанного Stanford Visualization Group, которое использует куб данных для каждой плитки для визуализации и изучения большого набора географических данных. Он может использоваться только для набора точечных данных, но может быть интересным способом.
http://vis.stanford.edu/papers/immens
Vizzuality с их платформой CartoDB и библиотекой Torque также как-то экспериментируют с тем, как рисовать большие объемы данных.
http://cartodb.github.io/torque/
https://github.com/CartoDB/torque/tree/new_torque
источник