He estado buscando una solución sólida que me permitiera crear un mapa web y superponer polígonos vectoriales sin demorar mucho en cargar dichos datos con el objetivo de permitirme hacer que cada polígono muestre un color diferente en un evento de desplazamiento.
Hasta donde sé, hay 3 opciones específicas para lograr esto a través de lienzo, SVG, Flash.
Parece que Flash sería la mejor solución si funcionara en iPhones / ipads de Apple, ya que parece proporcionar la representación más rápida y la pantalla más limpia. El lienzo parece ser la segunda mejor opción, pero lleva mucho tiempo si tiene cientos de polígonos que se muestran en un mapa, mientras que SVG tarda aún más en renderizarse.
Yo casi perdido la esperanza de encontrar una solución a este problema , pero hoy me encontré con una compañía llamada GISCloud http://www.giscloud.com (actualmente en beta con inscripción gratuita).
Esta empresa, ALGUNA VEZ, logró encontrar una forma increíble de representar cientos de vectores en un mapa en tiempo casi real. Me sorprendió su enfoque y mi pregunta a la comunidad se relaciona con la forma en que podemos replicar su enfoque para usarlo con tecnologías existentes como folletos, capas abiertas, cera ...
Echa un vistazo por ti mismo viendo esta increíble demostración: http://www.giscloud.com/map/284/africa
Asegúrese de pasar el cursor sobre cualquiera de los polígonos de la página y pruebe los controles de zoom para ver que estos polígonos son vectores.
Lo que he notado al mirar las solicitudes con firebug es que el mapa está solicitando archivos json específicos. Parece que, dependiendo del nivel / área de zoom, se solicitan varios archivos json.
También debería mencionar aquí que una vez que giscloud carga los datos en la página que se cierne sobre un vector, cambia inmediatamente el color sin crear una nueva solicitud.
EJEMPLOS
- 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
Supongo que la estructura de la URL sigue la lógica estándar del servicio de mosaico (por ejemplo, la tercera a la última carpeta es el nivel de zoom ...).
En cualquier caso, he analizado los datos reales de estos archivos json y parece que la lógica que están utilizando sigue algún tipo de lógica mediante la cual crean sus vectores basados en estos valores de datos:
- ancho / alto: definen el ancho y alto de los datos que se sirven en cada solicitud json
- píxeles: aquí definen valores de píxeles que supongo que de alguna manera se relacionan con algunas coordenadas generales de píxeles x / y para niveles de puntos generalizados. Supongo que de alguna manera tienen una forma de simplificar automáticamente la región según el nivel de zoom. Supongo que mediante el uso de coordenadas de píxeles, supongo que están reduciendo drásticamente el tamaño de los datos que deben cargarse en comparación con los datos de lat / long.
- estilos: aquí definen dos valores css RGB. "F" representa el color del archivo poligonal y "S" representa el color del borde del polígono.
- geom: aquí es donde supongo que de alguna manera están definiendo específicamente la definición de cada polígono dentro del mosaico que se está cargando donde dichos datos se definen en función de la ventana del contenedor del mapa. Lo que también es interesante es que cada entrada tiene un valor "S" que supongo que se usa como un atributo opcional o un valor de enlace de característica y al final de cada entrada aquí hay un área que parece definir un ID por vector específico junto con el ID de capa que supongo se utiliza para unir de alguna manera los datos de cada solicitud de mosaico json que se llama.
También estoy asumiendo que de alguna manera han descubierto una manera de determinar y dividir automáticamente los datos que deben cargarse para cada mosaico, dependiendo del tamaño de los datos que deberían cargarse para el mosaico solicitado.
Aquí hay un desglose extraído de una de estas solicitudes:
{"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"},
{...}
...
]
}
¿Cómo podemos replicar el mismo tipo (o similar) de velocidad usando postgis (que es lo que parecen estar usando también)?
fuente
Respuestas:
He visto esta técnica utilizada en el pasado. Me lo explicó Zain Memon (de Trulia), quien ayudó a dar su opinión cuando Michal Migurski estaba creando TileStache. Zain lo revisó mientras explicaba su demostración de Trulia que usa esta técnica en una de nuestras reuniones más antiguas de SF GeoMeetup hace algún tiempo . De hecho, si estás en San Francisco la próxima semana (este es mi intento flojo en un enchufe, él tocará esto , así que siéntete libre de presentarte :)
OK, ahora a la explicación.
Primero, está mirando un poco en el lugar equivocado cuando mira los archivos json de arriba.
Déjame explicarte (tan breve como pueda), por qué.
Los mosaicos se pasan como mosaicos renderizados normales, no es gran cosa allí, sabemos cómo hacerlo y, por lo tanto, no necesito explicar eso.
Si lo inspeccionas en Firebug, verás que también obtienes un montón de imágenes que parecen estar en blanco, como esta .
¿Por qué está en blanco? No lo es. Los píxeles contienen datos, simplemente no datos tradicionales de imágenes visibles. Están utilizando una técnica muy inteligente para pasar datos codificados en los mismos píxeles.
Lo que ha estado sucediendo en la última década es que la gente ha estado intercambiando datos de legibilidad y portabilidad de formatos a expensas de la eficiencia del almacenamiento.
Tome este ejemplo de datos de muestra xml:
OK, ¿cuántas mordidas para transferir esto? Siempre que seamos utf8 (1 byte por carácter cuando se trata con este contenido). Bueno, tenemos alrededor de 176 caracteres (sin contar tabulaciones o espacios), lo que hace que estos 176 bytes (esto es optimista por varias razones que omitiré por simplicidad). Eso sí, esto es por 2 puntos!
Aún así, un asno inteligente que no entiende de qué está hablando, en algún lugar, afirmará que "json te da una mayor compresión".
Bien, pongamos las mismas tonterías xml que json:
¿Cuántos bytes hay aquí? Decir ~ 115 caracteres. Incluso hice trampa un poco y lo hice más pequeño.
Digamos que mi área cubre 256x256 píxeles y que tengo un nivel de zoom tan alto que cada entidad se representa como un píxel y tengo tantas funciones que está llena. ¿Cuántos datos necesito para mostrar que 65,536 características?
54 caracteres (o bytes utf, e incluso estoy ignorando otras cosas) por entrada de "función" multiplicada x 65,536 = 3,538,944 o aproximadamente 3.3MB
Creo que te haces una idea.
Pero así es como transportamos datos en una arquitectura orientada a servicios. Basura legible hinchada.
¿Qué pasa si quisiera transportar todo en un esquema binario que inventé yo mismo? Digamos que, en cambio, codifiqué esa información en una sola imagen de banda (es decir, blanco y negro). Y decidí que 0 significa vendido, y 1 significa disponible, y 2 significa que no lo sé. Heck, en 1 byte, tengo 256 opciones que puedo usar, y solo estoy usando 2 o tres de ellas para este ejemplo.
¿Cuál es el costo de almacenamiento de eso? 256x256x 1 (solo una banda). 65,536 bytes o 0.06MB. Y esto ni siquiera toma en consideración otras técnicas de compresión que obtengo gratis de varias décadas de investigación en compresión de imágenes.
En este punto, debería preguntarse por qué las personas no simplemente envían datos codificados en formato binario en lugar de serializar a json. Bueno, primero, resulta que javascript es un gran momento para transportar datos binarios , por eso la gente no ha hecho esto históricamente.
Algunas personas utilizaron un trabajo increíble cuando aparecieron las nuevas características de HTML5, particularmente el lienzo . Entonces, ¿cuál es esta increíble solución? Resulta que puede enviar datos a través del cable codificado en lo que parece ser una imagen, luego puede insertar esa imagen en un lienzo HTML5, lo que le permite manipular los píxeles directamente . Ahora tiene una forma de obtener esos datos, decodificarlos en el lado del cliente y generar los objetos json en el cliente.
Detente un momento y piensa en esto.
Tiene una forma de codificar una gran cantidad de datos georreferenciados significativos en un formato altamente comprimido, órdenes de magnitud más pequeños que cualquier otra cosa que se haga tradicionalmente en aplicaciones web, y manipularlos en JavaScript.
El lienzo HTML ni siquiera necesita ser usado para dibujar, ¡solo se usa como un mecanismo de decodificación binaria!
De eso se tratan todas esas imágenes que ves en Firebug. Una imagen, con los datos codificados para cada mosaico que se descarga. Son súper pequeños, pero tienen datos significativos.
Entonces, ¿cómo codifica esto en el lado del servidor? Bueno, debe generalizar los datos en el lado del servidor y crear un mosaico significativo para cada nivel de zoom que tenga los datos codificados. Actualmente, para hacer esto, tiene que implementar el suyo: no existe una solución de código abierto lista para usar, pero tiene todas las herramientas que necesita para hacerlo. PostGIS hará la generalización a través de GEOS, TileCache se puede usar para almacenar en caché y ayudarlo a activar la generación de los mosaicos. En el lado del cliente, necesitará usar HTML5 Canvas para pasar los "mosaicos falsos" especiales y luego puede usar OpenLayers para crear objetos javascript reales del lado del cliente que representan los vectores con efectos de mouse.
Si necesita codificar más datos, recuerde que siempre puede generar imágenes RGBA por píxel (que le da 4 bytes por píxel o 4,294,967,296 números que puede representar por píxel ). Puedo pensar en varias formas de usar eso :)
Actualización : Responde la pregunta QGIS a continuación.
QGIS, como la mayoría de los otros GIS de escritorio , no tiene un conjunto fijo de niveles de zoom. Tienen la flexibilidad de hacer zoom a cualquier escala y solo renderizar. ¿Pueden mostrar datos de WMS o fuentes basadas en mosaicos? Claro que pueden, pero la mayoría de las veces son realmente tontos al respecto: Zoom en una medida diferente, calcular el cuadro delimitador, calcular el mosaico requerido, agarrarlos, mostrarlos. La mayoría de las veces ignoran otras cosas, como cachés de encabezado http que lo harían para que no tuvieran que volver a buscar. A veces implementan un mecanismo de caché simple (almacene el mosaico, si lo solicita, verifique el mosaico, no lo solicite). Pero esto no es suficiente.
Con esta técnica, los mosaicos y los vectores deben volverse a buscar en cada nivel de zoom . ¿Por qué? Porque los vectores se han generalizado para acomodar los niveles de zoom.
En cuanto al truco completo de colocar los mosaicos en un lienzo HTML5 para que pueda acceder a los búferes, todo eso no es necesario. QGIS le permite escribir código en Python y C ++, ambos lenguajes tienen un excelente soporte para manejar buffers binarios, por lo que esta solución es realmente irrelevante para esta plataforma.
* ACTUALIZACIÓN 2 **:
Hubo una pregunta sobre cómo crear los mosaicos de vectores generalizados en primer lugar (primer paso para bebés antes de poder serializar los resultados en imágenes). Quizás no aclare lo suficiente. Tilestache le permitirá crear "mosaicos vectoriales" efectivos de sus datos en cada nivel de zoom (incluso tiene una opción que le permite recortar o no recortar los datos cuando pasa el límite del mosaico). Esto se encarga de separar los vectores en mosaicos en varios niveles de zoom. Elegiría la opción "no recortar" (pero elegirá un mosaico arbitrario donde cubra más área). Luego puede alimentar cada vector a través de la opción de generalización GEOS con un gran número, de hecho, desea que sea lo suficientemente grande como para que las polilíneas y los polígonos colapsen sobre sí mismos, porque si lo hacen, puede eliminarlos del nivel de zoom ya que para esa etapa son irrelevante. Tilestache incluso le permite escribir proveedores de datos pitónicos fáciles donde puede poner esta lógica. En esa etapa, puede elegir servirlos como archivos json (como lo hacen con algunas de las muestras de mapas africanos) o como geometrías serializadas en los png, como lo hacen en otras muestras (o la de Trulia) que di anteriormente.
fuente
Directo del desarrollador Dino Ravnic en una publicación reciente de la lista de correo :
Por lo tanto, parece que el lado del cliente es la parte fácil. Es impresionante que los datos se procesen sin almacenamiento en caché.
También menciona un servicio de alojamiento que puede ser de su interés. Es posible que desee sopesar el costo de intentar recrear esto con el costo de usar un servicio listo para usar.
fuente
Como describí en la lista OSGeo, la clave está en entregar datos como mosaicos vectoriales JSON que tienen píxeles para la geometría de subpíxeles y geometría generalizada para aquellas características que serán realmente visibles en cierto nivel. El rendimiento es excelente porque esta técnica elimina toda la información vectorial innecesaria y deja solo aquellos vectores que realmente tendrán un impacto visual en el mapa. Los píxeles están ahí para llenar los huecos y colocarse en lugar de esos vectores de subpíxeles. Eso es todo con respecto al formato de mosaico.
En el lado del backend está el verdadero trabajo pesado. No estamos utilizando TileStache ni ningún otro motor de mapas, ya que escribimos el nuestro que puede, con varias optimizaciones, producir tales gráficos vectoriales en tiempo real.
Primero, comenzamos a entregar mosaicos de mapas como SWF y, últimamente, habilitamos la salida a JSON para poder usar HTML5 Canvas para representar los gráficos. A continuación puede encontrar un punto de referencia que compara este tipo de tecnología vectorial con tecnología raster (mapnik). Para una comparación justa, solo busque resultados en modo CGI.
http://www.giscloud.com/blog/realtime-map-tile-rendering-benchmark-rasters-vs-vectors/
Estamos planeando proporcionar esta tecnología como un servicio de alojamiento de mosaicos de mapas. La idea es alojar sus datos geográficos en la nube y, a través de HTML5, entregarlos en cualquier cliente de mapas a alta velocidad, sin necesidad de precachear los mosaicos. Si está interesado en unirse a esta versión beta, no dude en contactarnos aquí: http://www.giscloud.com/contact/
fuente
Parece que recientemente se hizo una pregunta muy similar en el foro OSGeo Open Layers , con los desarrolladores de GIS Cloud describiendo su enfoque, que es una mezcla interesante de geometrías GeoJSON y píxeles estáticos. En realidad, generan todos los mosaicos de vectores sobre la marcha en lugar de usar un caché preconstruido de archivos GeoJSON.
Esri ha implementado un enfoque similar, utilizando ArcGIS Server y Feature Layers , que pueden generalizar las geometrías sobre la marcha y enviarlas por cable como JSON.
Para un método directo que realmente puede implementar ahora, puede construir mosaicos vectoriales con Tilestache (que tiene soporte PostGIS ) y consumirlos en Polymaps . Polymaps usa SVG, pero el rendimiento es bastante bueno , y las reglas CSS para diseñar elementos de mapa, por lo que la representación de características depende totalmente de usted. Aquí hay una publicación de blog que trata sobre algo similar a lo que está preguntando.
fuente
Jugué con OpenLayers usando Canvas y obtuve resultados razonables.
Como se mencionó en las otras respuestas: para entregar y mostrar vectores sobre la marcha, deben generalizarse para cada nivel de zoom y cada conjunto de datos. Además, puede usar la codificación de polilínea de Google para reducir considerablemente el tamaño.
Usé un mecanismo de entrega simple. Cada geometría era una función de JavaScript dentro de una respuesta HTTP de JavaScript. ¡No es tan avanzado como la entrega de vectores basada en mosaicos, pero es simple y de código abierto!
No pude probar Google Maps v3 con Canvas, pero he visto un par de demos del New York Times que me impresionaron.
fuente
No sé exactamente qué solución utiliza esta empresa (tal vez podría preguntarles directamente), pero tengo una idea.
La solución clave para mejorar la transferencia de red y la velocidad de representación de los datos vectoriales es generalizarlos de acuerdo con el nivel de zoom: la transferencia y representación a un nivel de zoom alto de miles de objetos diseñados para un nivel de zoom mucho más bajo a menudo consume mucho tiempo (y también inútil porque la pantalla final generalmente no es legible; vea, por ejemplo, esta imagen ). Para implementar eso, la base de datos del servidor postgis debe ser multiescala : para cada nivel de zoom, debe haber una representación del objeto adecuada para este nivel de zoom. Estas diferentes representaciones se pueden calcular automáticamente utilizando técnicas de generalización.. Además, los datos vectoriales enviados por el servidor al cliente no deberían depender solo de la extensión espacial, sino también del nivel de zoom: el servidor envía datos adecuados según el nivel de zoom. Este es el enfoque defendido en este excelente artículo :-)
fuente
Hay un documento interesante, una demostración y el código fuente de un software desarrollado por Stanford Visualization Group que utiliza un cubo de datos para cada mosaico para visualizar y explorar un gran conjunto de datos geográficos. Se puede usar solo para el conjunto de datos de puntos, pero puede ser una forma interesante.
http://vis.stanford.edu/papers/immens
Vizzuality con su plataforma CartoDB y la biblioteca llamada Torque también están experimentando de alguna manera cómo dibujar un gran volumen de datos.
http://cartodb.github.io/torque/
https://github.com/CartoDB/torque/tree/new_torque
fuente